summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2024-11-14 11:39:47 +0000
committerMark Brown <broonie@kernel.org>2024-11-14 11:39:47 +0000
commit07db6d5e12bbc2d698ca01113b0db62bc7b80e3f (patch)
treee650149258728f0115a6c320e7b548dcef9d7352 /sound
parentde35b06bf15cb56c96c7a69474e305852cc170e3 (diff)
parent2ae6da569e34e1d26c5275442d17ffd75fd343b3 (diff)
ASoC: Merge up fixes
Needed for new Intel board file changes.
Diffstat (limited to 'sound')
-rw-r--r--sound/hda/intel-dsp-config.c4
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c21
-rw-r--r--sound/soc/codecs/cs42l51.c7
-rw-r--r--sound/soc/codecs/lpass-rx-macro.c15
-rw-r--r--sound/soc/codecs/max9768.c11
-rw-r--r--sound/soc/codecs/pcm3060-i2c.c4
-rw-r--r--sound/soc/codecs/pcm3060-spi.c4
-rw-r--r--sound/soc/codecs/pcm3060.c4
-rw-r--r--sound/soc/codecs/pcm3060.h2
-rw-r--r--sound/soc/codecs/rt5640.c27
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c2
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c1
-rw-r--r--sound/soc/codecs/wcd937x.c12
-rw-r--r--sound/soc/codecs/wcd937x.h4
-rw-r--r--sound/soc/fsl/fsl_micfil.c81
-rw-r--r--sound/soc/generic/audio-graph-card2.c3
-rw-r--r--sound/soc/intel/atom/sst/sst_acpi.c64
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c48
-rw-r--r--sound/soc/intel/boards/sof_sdw.c8
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-lnl-match.c38
-rw-r--r--sound/soc/qcom/Kconfig1
-rw-r--r--sound/soc/qcom/sc7280.c10
-rw-r--r--sound/soc/soc-dapm.c2
-rw-r--r--sound/soc/sof/amd/acp.c10
-rw-r--r--sound/soc/sof/intel/hda-dai-ops.c23
-rw-r--r--sound/soc/sof/intel/hda-dai.c37
-rw-r--r--sound/soc/sof/ipc4-topology.c15
-rw-r--r--sound/soc/sof/sof-client-probes-ipc4.c1
-rw-r--r--sound/soc/stm/stm32_sai_sub.c6
-rw-r--r--sound/soc/stm/stm32_spdifrx.c2
30 files changed, 395 insertions, 72 deletions
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index f018bd779862..9f849e05ce79 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -723,6 +723,10 @@ static const struct config_entry acpi_config_table[] = {
/* BayTrail */
{
.flags = FLAG_SST_OR_SOF_BYT,
+ .acpi_hid = "LPE0F28",
+ },
+ {
+ .flags = FLAG_SST_OR_SOF_BYT,
.acpi_hid = "80860F28",
},
/* CherryTrail */
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 98f9237b7ad7..2436e8deb2be 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -231,6 +231,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M4"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21M5"),
}
},
@@ -329,6 +336,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "E1404FA"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"),
}
},
@@ -391,6 +405,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Xiaomi Book Pro 14 2022"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Razer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"),
}
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index e4827b8c2bde..6e51954bdb1e 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -747,8 +747,10 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
cs42l51->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_LOW);
- if (IS_ERR(cs42l51->reset_gpio))
- return PTR_ERR(cs42l51->reset_gpio);
+ if (IS_ERR(cs42l51->reset_gpio)) {
+ ret = PTR_ERR(cs42l51->reset_gpio);
+ goto error;
+ }
if (cs42l51->reset_gpio) {
dev_dbg(dev, "Release reset gpio\n");
@@ -780,6 +782,7 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap)
return 0;
error:
+ gpiod_set_value_cansleep(cs42l51->reset_gpio, 1);
regulator_bulk_disable(ARRAY_SIZE(cs42l51->supplies),
cs42l51->supplies);
return ret;
diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c
index ef7a70fa6966..febbbe073962 100644
--- a/sound/soc/codecs/lpass-rx-macro.c
+++ b/sound/soc/codecs/lpass-rx-macro.c
@@ -202,12 +202,14 @@
#define CDC_RX_RXn_RX_PATH_SEC3(rx, n) (0x042c + rx->rxn_reg_stride * n)
#define CDC_RX_RX0_RX_PATH_SEC4 (0x0430)
#define CDC_RX_RX0_RX_PATH_SEC7 (0x0434)
-#define CDC_RX_RXn_RX_PATH_SEC7(rx, n) (0x0434 + rx->rxn_reg_stride * n)
+#define CDC_RX_RXn_RX_PATH_SEC7(rx, n) \
+ (0x0434 + (rx->rxn_reg_stride * n) + ((n > 1) ? rx->rxn_reg_stride2 : 0))
#define CDC_RX_DSM_OUT_DELAY_SEL_MASK GENMASK(2, 0)
#define CDC_RX_DSM_OUT_DELAY_TWO_SAMPLE 0x2
#define CDC_RX_RX0_RX_PATH_MIX_SEC0 (0x0438)
#define CDC_RX_RX0_RX_PATH_MIX_SEC1 (0x043C)
-#define CDC_RX_RXn_RX_PATH_DSM_CTL(rx, n) (0x0440 + rx->rxn_reg_stride * n)
+#define CDC_RX_RXn_RX_PATH_DSM_CTL(rx, n) \
+ (0x0440 + (rx->rxn_reg_stride * n) + ((n > 1) ? rx->rxn_reg_stride2 : 0))
#define CDC_RX_RXn_DSM_CLK_EN_MASK BIT(0)
#define CDC_RX_RX0_RX_PATH_DSM_CTL (0x0440)
#define CDC_RX_RX0_RX_PATH_DSM_DATA1 (0x0444)
@@ -645,6 +647,7 @@ struct rx_macro {
int rx_mclk_cnt;
enum lpass_codec_version codec_version;
int rxn_reg_stride;
+ int rxn_reg_stride2;
bool is_ear_mode_on;
bool hph_pwr_mode;
bool hph_hd2_mode;
@@ -1929,9 +1932,6 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
CDC_RX_PATH_PGA_MUTE_MASK, 0x0);
}
- if (j == INTERP_AUX)
- dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, 2);
-
int_mux_cfg0 = CDC_RX_INP_MUX_RX_INT0_CFG0 + j * 8;
int_mux_cfg1 = int_mux_cfg0 + 4;
int_mux_cfg0_val = snd_soc_component_read(component, int_mux_cfg0);
@@ -2702,9 +2702,6 @@ static int rx_macro_enable_interp_clk(struct snd_soc_component *component,
main_reg = CDC_RX_RXn_RX_PATH_CTL(rx, interp_idx);
dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, interp_idx);
- if (interp_idx == INTERP_AUX)
- dsm_reg = CDC_RX_RXn_RX_PATH_DSM_CTL(rx, 2);
-
rx_cfg2_reg = CDC_RX_RXn_RX_PATH_CFG2(rx, interp_idx);
if (SND_SOC_DAPM_EVENT_ON(event)) {
@@ -3821,6 +3818,7 @@ static int rx_macro_probe(struct platform_device *pdev)
case LPASS_CODEC_VERSION_2_0:
case LPASS_CODEC_VERSION_2_1:
rx->rxn_reg_stride = 0x80;
+ rx->rxn_reg_stride2 = 0xc;
def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_pre_2_5_defaults);
reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL);
if (!reg_defaults)
@@ -3834,6 +3832,7 @@ static int rx_macro_probe(struct platform_device *pdev)
case LPASS_CODEC_VERSION_2_7:
case LPASS_CODEC_VERSION_2_8:
rx->rxn_reg_stride = 0xc0;
+ rx->rxn_reg_stride2 = 0x0;
def_count = ARRAY_SIZE(rx_defaults) + ARRAY_SIZE(rx_2_5_defaults);
reg_defaults = kmalloc_array(def_count, sizeof(struct reg_default), GFP_KERNEL);
if (!reg_defaults)
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index e4793a5d179e..8af3c7e5317f 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -54,10 +54,17 @@ static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
struct max9768 *max9768 = snd_soc_component_get_drvdata(c);
+ bool val = !ucontrol->value.integer.value[0];
+ int ret;
- gpiod_set_value_cansleep(max9768->mute, !ucontrol->value.integer.value[0]);
+ if (val != gpiod_get_value_cansleep(max9768->mute))
+ ret = 1;
+ else
+ ret = 0;
- return 0;
+ gpiod_set_value_cansleep(max9768->mute, val);
+
+ return ret;
}
static const DECLARE_TLV_DB_RANGE(volume_tlv,
diff --git a/sound/soc/codecs/pcm3060-i2c.c b/sound/soc/codecs/pcm3060-i2c.c
index 5330cf46b127..3816b25a8ead 100644
--- a/sound/soc/codecs/pcm3060-i2c.c
+++ b/sound/soc/codecs/pcm3060-i2c.c
@@ -2,7 +2,7 @@
//
// PCM3060 I2C driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+// Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
#include <linux/i2c.h>
#include <linux/module.h>
@@ -55,5 +55,5 @@ static struct i2c_driver pcm3060_i2c_driver = {
module_i2c_driver(pcm3060_i2c_driver);
MODULE_DESCRIPTION("PCM3060 I2C driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
+MODULE_AUTHOR("Kirill Marinushkin <k.marinushkin@gmail.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060-spi.c b/sound/soc/codecs/pcm3060-spi.c
index 3b79734b832b..6095841f2f56 100644
--- a/sound/soc/codecs/pcm3060-spi.c
+++ b/sound/soc/codecs/pcm3060-spi.c
@@ -2,7 +2,7 @@
//
// PCM3060 SPI driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+// Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
#include <linux/module.h>
#include <linux/spi/spi.h>
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = {
module_spi_driver(pcm3060_spi_driver);
MODULE_DESCRIPTION("PCM3060 SPI driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
+MODULE_AUTHOR("Kirill Marinushkin <k.marinushkin@gmail.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060.c b/sound/soc/codecs/pcm3060.c
index 586ec8c7246c..8974200652e7 100644
--- a/sound/soc/codecs/pcm3060.c
+++ b/sound/soc/codecs/pcm3060.c
@@ -2,7 +2,7 @@
//
// PCM3060 codec driver
//
-// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+// Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
#include <linux/module.h>
#include <sound/pcm_params.h>
@@ -343,5 +343,5 @@ int pcm3060_probe(struct device *dev)
EXPORT_SYMBOL(pcm3060_probe);
MODULE_DESCRIPTION("PCM3060 codec driver");
-MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
+MODULE_AUTHOR("Kirill Marinushkin <k.marinushkin@gmail.com>");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/pcm3060.h b/sound/soc/codecs/pcm3060.h
index 5e1185e7b03d..1b96835600b4 100644
--- a/sound/soc/codecs/pcm3060.h
+++ b/sound/soc/codecs/pcm3060.h
@@ -2,7 +2,7 @@
/*
* PCM3060 codec driver
*
- * Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
+ * Copyright (C) 2018 Kirill Marinushkin <k.marinushkin@gmail.com>
*/
#ifndef _SND_SOC_PCM3060_H
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 16f3425a3e35..855139348edb 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2419,10 +2419,20 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
return IRQ_HANDLED;
}
-static void rt5640_cancel_work(void *data)
+static void rt5640_disable_irq_and_cancel_work(void *data)
{
struct rt5640_priv *rt5640 = data;
+ if (rt5640->jd_gpio_irq_requested) {
+ free_irq(rt5640->jd_gpio_irq, rt5640);
+ rt5640->jd_gpio_irq_requested = false;
+ }
+
+ if (rt5640->irq_requested) {
+ free_irq(rt5640->irq, rt5640);
+ rt5640->irq_requested = false;
+ }
+
cancel_delayed_work_sync(&rt5640->jack_work);
cancel_delayed_work_sync(&rt5640->bp_work);
}
@@ -2463,13 +2473,7 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
if (!rt5640->jack)
return;
- if (rt5640->jd_gpio_irq_requested)
- free_irq(rt5640->jd_gpio_irq, rt5640);
-
- if (rt5640->irq_requested)
- free_irq(rt5640->irq, rt5640);
-
- rt5640_cancel_work(rt5640);
+ rt5640_disable_irq_and_cancel_work(rt5640);
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
rt5640_disable_micbias1_ovcd_irq(component);
@@ -2477,8 +2481,6 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
}
- rt5640->jd_gpio_irq_requested = false;
- rt5640->irq_requested = false;
rt5640->jd_gpio = NULL;
rt5640->jack = NULL;
}
@@ -2798,7 +2800,8 @@ static int rt5640_suspend(struct snd_soc_component *component)
if (rt5640->jack) {
/* disable jack interrupts during system suspend */
disable_irq(rt5640->irq);
- rt5640_cancel_work(rt5640);
+ cancel_delayed_work_sync(&rt5640->jack_work);
+ cancel_delayed_work_sync(&rt5640->bp_work);
}
snd_soc_component_force_bias_level(component, SND_SOC_BIAS_OFF);
@@ -3032,7 +3035,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c)
INIT_DELAYED_WORK(&rt5640->jack_work, rt5640_jack_work);
/* Make sure work is stopped on probe-error / remove */
- ret = devm_add_action_or_reset(&i2c->dev, rt5640_cancel_work, rt5640);
+ ret = devm_add_action_or_reset(&i2c->dev, rt5640_disable_irq_and_cancel_work, rt5640);
if (ret)
return ret;
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index 0abbd92cbc7e..25fc13687bc8 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -253,7 +253,7 @@ static int rt722_sdca_read_prop(struct sdw_slave *slave)
}
/* set the timeout values */
- prop->clk_stop_timeout = 200;
+ prop->clk_stop_timeout = 900;
/* wake-up event */
prop->wake_capable = 1;
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index ae360c97fe1e..0aeb88abbf52 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -1992,6 +1992,7 @@ static int tasdevice_dspfw_ready(const struct firmware *fmw,
break;
case 0x202:
case 0x400:
+ case 0x401:
tas_priv->fw_parse_variable_header =
fw_parse_variable_header_git;
tas_priv->fw_parse_program_data =
diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c
index a11f9be91da4..c9d5e67bf66e 100644
--- a/sound/soc/codecs/wcd937x.c
+++ b/sound/soc/codecs/wcd937x.c
@@ -714,12 +714,17 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
int hph_mode = wcd937x->hph_mode;
+ u8 val;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ val = WCD937X_DIGITAL_PDM_WD_CTL2_EN |
+ WCD937X_DIGITAL_PDM_WD_CTL2_TIMEOUT_SEL |
+ WCD937X_DIGITAL_PDM_WD_CTL2_HOLD_OFF;
snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2,
- BIT(0), BIT(0));
+ WCD937X_DIGITAL_PDM_WD_CTL2_MASK,
+ val);
break;
case SND_SOC_DAPM_POST_PMU:
usleep_range(1000, 1010);
@@ -740,7 +745,8 @@ static int wcd937x_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
hph_mode);
snd_soc_component_update_bits(component,
WCD937X_DIGITAL_PDM_WD_CTL2,
- BIT(0), 0x00);
+ WCD937X_DIGITAL_PDM_WD_CTL2_MASK,
+ 0x00);
break;
}
@@ -2048,6 +2054,8 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("HPHR Switch", WCD937X_HPH_R, 0, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port),
+ SOC_SINGLE_EXT("LO Switch", WCD937X_LO, 0, 1, 0,
+ wcd937x_get_swr_port, wcd937x_set_swr_port),
SOC_SINGLE_EXT("ADC1 Switch", WCD937X_ADC1, 1, 1, 0,
wcd937x_get_swr_port, wcd937x_set_swr_port),
diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h
index 35f3d48bd7dd..4afa48dcaf74 100644
--- a/sound/soc/codecs/wcd937x.h
+++ b/sound/soc/codecs/wcd937x.h
@@ -391,6 +391,10 @@
#define WCD937X_DIGITAL_PDM_WD_CTL0 0x3465
#define WCD937X_DIGITAL_PDM_WD_CTL1 0x3466
#define WCD937X_DIGITAL_PDM_WD_CTL2 0x3467
+#define WCD937X_DIGITAL_PDM_WD_CTL2_HOLD_OFF BIT(2)
+#define WCD937X_DIGITAL_PDM_WD_CTL2_TIMEOUT_SEL BIT(1)
+#define WCD937X_DIGITAL_PDM_WD_CTL2_EN BIT(0)
+#define WCD937X_DIGITAL_PDM_WD_CTL2_MASK GENMASK(2, 0)
#define WCD937X_DIGITAL_INTR_MODE 0x346A
#define WCD937X_DIGITAL_INTR_MASK_0 0x346B
#define WCD937X_DIGITAL_INTR_MASK_1 0x346C
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index 4e65966d54fc..8c15389c9a04 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -28,6 +28,13 @@
#define MICFIL_OSR_DEFAULT 16
+#define MICFIL_NUM_RATES 7
+#define MICFIL_CLK_SRC_NUM 3
+/* clock source ids */
+#define MICFIL_AUDIO_PLL1 0
+#define MICFIL_AUDIO_PLL2 1
+#define MICFIL_CLK_EXT3 2
+
enum quality {
QUALITY_HIGH,
QUALITY_MEDIUM,
@@ -45,9 +52,12 @@ struct fsl_micfil {
struct clk *mclk;
struct clk *pll8k_clk;
struct clk *pll11k_clk;
+ struct clk *clk_src[MICFIL_CLK_SRC_NUM];
struct snd_dmaengine_dai_dma_data dma_params_rx;
struct sdma_peripheral_config sdmacfg;
struct snd_soc_card *card;
+ struct snd_pcm_hw_constraint_list constraint_rates;
+ unsigned int constraint_rates_list[MICFIL_NUM_RATES];
unsigned int dataline;
char name[32];
int irq[MICFIL_IRQ_LINES];
@@ -68,6 +78,7 @@ struct fsl_micfil_soc_data {
bool imx;
bool use_edma;
bool use_verid;
+ bool volume_sx;
u64 formats;
};
@@ -77,6 +88,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mm = {
.fifo_depth = 8,
.dataline = 0xf,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .volume_sx = true,
};
static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
@@ -85,6 +97,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx8mp = {
.fifo_depth = 32,
.dataline = 0xf,
.formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .volume_sx = false,
};
static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
@@ -95,6 +108,7 @@ static struct fsl_micfil_soc_data fsl_micfil_imx93 = {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.use_edma = true,
.use_verid = true,
+ .volume_sx = false,
};
static const struct of_device_id fsl_micfil_dt_ids[] = {
@@ -318,7 +332,26 @@ static int hwvad_detected(struct snd_kcontrol *kcontrol,
return 0;
}
-static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
+static const struct snd_kcontrol_new fsl_micfil_volume_controls[] = {
+ SOC_SINGLE_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH2 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH3 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH4 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH5 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH6 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0, gain_tlv),
+ SOC_SINGLE_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
+ MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0, gain_tlv),
+};
+
+static const struct snd_kcontrol_new fsl_micfil_volume_sx_controls[] = {
SOC_SINGLE_SX_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL,
MICFIL_OUTGAIN_CHX_SHIFT(0), 0x8, 0xF, gain_tlv),
SOC_SINGLE_SX_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL,
@@ -335,6 +368,9 @@ static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
MICFIL_OUTGAIN_CHX_SHIFT(6), 0x8, 0xF, gain_tlv),
SOC_SINGLE_SX_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL,
MICFIL_OUTGAIN_CHX_SHIFT(7), 0x8, 0xF, gain_tlv),
+};
+
+static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
SOC_ENUM_EXT("MICFIL Quality Select",
fsl_micfil_quality_enum,
micfil_quality_get, micfil_quality_set),
@@ -450,12 +486,34 @@ static int fsl_micfil_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_micfil *micfil = snd_soc_dai_get_drvdata(dai);
+ unsigned int rates[MICFIL_NUM_RATES] = {8000, 11025, 16000, 22050, 32000, 44100, 48000};
+ int i, j, k = 0;
+ u64 clk_rate;
if (!micfil) {
dev_err(dai->dev, "micfil dai priv_data not set\n");
return -EINVAL;
}
+ micfil->constraint_rates.list = micfil->constraint_rates_list;
+ micfil->constraint_rates.count = 0;
+
+ for (j = 0; j < MICFIL_NUM_RATES; j++) {
+ for (i = 0; i < MICFIL_CLK_SRC_NUM; i++) {
+ clk_rate = clk_get_rate(micfil->clk_src[i]);
+ if (clk_rate != 0 && do_div(clk_rate, rates[j]) == 0) {
+ micfil->constraint_rates_list[k++] = rates[j];
+ micfil->constraint_rates.count++;
+ break;
+ }
+ }
+ }
+
+ if (micfil->constraint_rates.count > 0)
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &micfil->constraint_rates);
+
return 0;
}
@@ -814,6 +872,20 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
return 0;
}
+static int fsl_micfil_component_probe(struct snd_soc_component *component)
+{
+ struct fsl_micfil *micfil = snd_soc_component_get_drvdata(component);
+
+ if (micfil->soc->volume_sx)
+ snd_soc_add_component_controls(component, fsl_micfil_volume_sx_controls,
+ ARRAY_SIZE(fsl_micfil_volume_sx_controls));
+ else
+ snd_soc_add_component_controls(component, fsl_micfil_volume_controls,
+ ARRAY_SIZE(fsl_micfil_volume_controls));
+
+ return 0;
+}
+
static const struct snd_soc_dai_ops fsl_micfil_dai_ops = {
.probe = fsl_micfil_dai_probe,
.startup = fsl_micfil_startup,
@@ -835,6 +907,7 @@ static struct snd_soc_dai_driver fsl_micfil_dai = {
static const struct snd_soc_component_driver fsl_micfil_component = {
.name = "fsl-micfil-dai",
+ .probe = fsl_micfil_component_probe,
.controls = fsl_micfil_snd_controls,
.num_controls = ARRAY_SIZE(fsl_micfil_snd_controls),
.legacy_dai_naming = 1,
@@ -1160,6 +1233,12 @@ static int fsl_micfil_probe(struct platform_device *pdev)
fsl_asoc_get_pll_clocks(&pdev->dev, &micfil->pll8k_clk,
&micfil->pll11k_clk);
+ micfil->clk_src[MICFIL_AUDIO_PLL1] = micfil->pll8k_clk;
+ micfil->clk_src[MICFIL_AUDIO_PLL2] = micfil->pll11k_clk;
+ micfil->clk_src[MICFIL_CLK_EXT3] = devm_clk_get(&pdev->dev, "clkext3");
+ if (IS_ERR(micfil->clk_src[MICFIL_CLK_EXT3]))
+ micfil->clk_src[MICFIL_CLK_EXT3] = NULL;
+
/* init regmap */
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(regs))
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 747afe7d6f34..045ca7f5033b 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -270,16 +270,19 @@ static enum graph_type __graph_get_type(struct device_node *lnk)
if (of_node_name_eq(np, GRAPH_NODENAME_MULTI)) {
ret = GRAPH_MULTI;
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
goto out_put;
}
if (of_node_name_eq(np, GRAPH_NODENAME_DPCM)) {
ret = GRAPH_DPCM;
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
goto out_put;
}
if (of_node_name_eq(np, GRAPH_NODENAME_C2C)) {
ret = GRAPH_C2C;
+ fw_devlink_purge_absent_suppliers(&np->fwnode);
goto out_put;
}
diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c
index 9956dc63db74..257180630475 100644
--- a/sound/soc/intel/atom/sst/sst_acpi.c
+++ b/sound/soc/intel/atom/sst/sst_acpi.c
@@ -125,6 +125,28 @@ static const struct sst_res_info bytcr_res_info = {
.acpi_ipc_irq_index = 0
};
+/* For "LPE0F28" ACPI device found on some Android factory OS models */
+static const struct sst_res_info lpe8086_res_info = {
+ .shim_offset = 0x140000,
+ .shim_size = 0x000100,
+ .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR,
+ .ssp0_offset = 0xa0000,
+ .ssp0_size = 0x1000,
+ .dma0_offset = 0x98000,
+ .dma0_size = 0x4000,
+ .dma1_offset = 0x9c000,
+ .dma1_size = 0x4000,
+ .iram_offset = 0x0c0000,
+ .iram_size = 0x14000,
+ .dram_offset = 0x100000,
+ .dram_size = 0x28000,
+ .mbox_offset = 0x144000,
+ .mbox_size = 0x1000,
+ .acpi_lpe_res_index = 1,
+ .acpi_ddr_index = 0,
+ .acpi_ipc_irq_index = 0
+};
+
static struct sst_platform_info byt_rvp_platform_data = {
.probe_data = &byt_fwparse_info,
.ipc_info = &byt_ipc_info,
@@ -268,10 +290,38 @@ static int sst_acpi_probe(struct platform_device *pdev)
mach->pdata = &chv_platform_data;
pdata = mach->pdata;
- ret = kstrtouint(id->id, 16, &dev_id);
- if (ret < 0) {
- dev_err(dev, "Unique device id conversion error: %d\n", ret);
- return ret;
+ if (!strcmp(id->id, "LPE0F28")) {
+ struct resource *rsrc;
+
+ /* Use regular BYT SST PCI VID:PID */
+ dev_id = 0x80860F28;
+ byt_rvp_platform_data.res_info = &lpe8086_res_info;
+
+ /*
+ * The "LPE0F28" ACPI device has separate IO-mem resources for:
+ * DDR, SHIM, MBOX, IRAM, DRAM, CFG
+ * None of which covers the entire LPE base address range.
+ * lpe8086_res_info.acpi_lpe_res_index points to the SHIM.
+ * Patch this to cover the entire base address range as expected
+ * by sst_platform_get_resources().
+ */
+ rsrc = platform_get_resource(pdev, IORESOURCE_MEM,
+ pdata->res_info->acpi_lpe_res_index);
+ if (!rsrc) {
+ dev_err(dev, "Invalid SHIM base\n");
+ return -EIO;
+ }
+ rsrc->start -= pdata->res_info->shim_offset;
+ rsrc->end = rsrc->start + 0x200000 - 1;
+ } else {
+ ret = kstrtouint(id->id, 16, &dev_id);
+ if (ret < 0) {
+ dev_err(dev, "Unique device id conversion error: %d\n", ret);
+ return ret;
+ }
+
+ if (soc_intel_is_byt_cr(pdev))
+ byt_rvp_platform_data.res_info = &bytcr_res_info;
}
dev_dbg(dev, "ACPI device id: %x\n", dev_id);
@@ -280,11 +330,6 @@ static int sst_acpi_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- if (soc_intel_is_byt_cr(pdev)) {
- /* override resource info */
- byt_rvp_platform_data.res_info = &bytcr_res_info;
- }
-
/* update machine parameters */
mach->mach_params.acpi_ipc_irq_index =
pdata->res_info->acpi_ipc_irq_index;
@@ -344,6 +389,7 @@ static void sst_acpi_remove(struct platform_device *pdev)
}
static const struct acpi_device_id sst_acpi_ids[] = {
+ { "LPE0F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
{ "80860F28", (unsigned long)&snd_soc_acpi_intel_baytrail_machines},
{ "808622A8", (unsigned long)&snd_soc_acpi_intel_cherrytrail_machines},
{ },
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 410eb36c37c9..9caa4407c1ca 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -17,6 +17,7 @@
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/device.h>
+#include <linux/device/bus.h>
#include <linux/dmi.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
@@ -32,6 +33,8 @@
#include "../atom/sst-atom-controls.h"
#include "../common/soc-intel-quirks.h"
+#define BYT_RT5640_FALLBACK_CODEC_DEV_NAME "i2c-rt5640"
+
enum {
BYT_RT5640_DMIC1_MAP,
BYT_RT5640_DMIC2_MAP,
@@ -1129,6 +1132,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF2 |
BYT_RT5640_MCLK_EN),
},
+ { /* Vexia Edu Atla 10 tablet */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+ BYT_RT5640_DIFF_MIC |
+ BYT_RT5640_SSP0_AIF2 |
+ BYT_RT5640_MCLK_EN),
+ },
{ /* Voyo Winpad A15 */
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
@@ -1694,9 +1712,33 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev)
codec_dev = acpi_get_first_physical_node(adev);
acpi_dev_put(adev);
- if (!codec_dev)
- return -EPROBE_DEFER;
- priv->codec_dev = get_device(codec_dev);
+
+ if (codec_dev) {
+ priv->codec_dev = get_device(codec_dev);
+ } else {
+ /*
+ * Special case for Android tablets where the codec i2c_client
+ * has been manually instantiated by x86_android_tablets.ko due
+ * to a broken DSDT.
+ */
+ codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
+ BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
+ if (!codec_dev)
+ return -EPROBE_DEFER;
+
+ if (!i2c_verify_client(codec_dev)) {
+ dev_err(dev, "Error '%s' is not an i2c_client\n",
+ BYT_RT5640_FALLBACK_CODEC_DEV_NAME);
+ put_device(codec_dev);
+ }
+
+ /* fixup codec name */
+ strscpy(byt_rt5640_codec_name, BYT_RT5640_FALLBACK_CODEC_DEV_NAME,
+ sizeof(byt_rt5640_codec_name));
+
+ /* bus_find_device() returns a reference no need to get() */
+ priv->codec_dev = codec_dev;
+ }
/*
* swap SSP0 if bytcr is detected
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index eaba91dad967..ea5249df8ac3 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -659,6 +659,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF1")
+ },
+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CF7")
},
.driver_data = (void *)(SOC_SDW_CODEC_SPKR),
diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
index 3c4e0c7ca8ee..094ed4b27cb0 100644
--- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c
@@ -225,6 +225,15 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt1318_1_adr[] = {
+ {
+ .adr = 0x000133025D131801ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt1318-1"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = {
{
.adr = 0x000130025D131801ull,
@@ -243,6 +252,15 @@ static const struct snd_soc_acpi_adr_device rt1318_2_group1_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt713_0_adr[] = {
+ {
+ .adr = 0x000031025D071301ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt713"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt714_0_adr[] = {
{
.adr = 0x000030025D071401ull,
@@ -378,6 +396,20 @@ static const struct snd_soc_acpi_link_adr lnl_sdw_rt1318_l12_rt714_l0[] = {
{}
};
+static const struct snd_soc_acpi_link_adr lnl_sdw_rt713_l0_rt1318_l1[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt713_0_adr),
+ .adr_d = rt713_0_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1318_1_adr),
+ .adr_d = rt1318_1_adr,
+ },
+ {}
+};
+
/* this table is used when there is no I2S codec present */
struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
/* mockup tests need to be first */
@@ -447,6 +479,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = {
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-lnl-rt1318-l12-rt714-l0.tplg"
},
+ {
+ .link_mask = BIT(0) | BIT(1),
+ .links = lnl_sdw_rt713_l0_rt1318_l1,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-lnl-rt713-l0-rt1318-l1.tplg"
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines);
diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
index 3687b9db5ed4..ca7a30ebd26a 100644
--- a/sound/soc/qcom/Kconfig
+++ b/sound/soc/qcom/Kconfig
@@ -209,6 +209,7 @@ config SND_SOC_SC7280
tristate "SoC Machine driver for SC7280 boards"
depends on I2C && SOUNDWIRE
select SND_SOC_QCOM_COMMON
+ select SND_SOC_QCOM_SDW
select SND_SOC_LPASS_SC7280
select SND_SOC_MAX98357A
select SND_SOC_WCD938X_SDW
diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c
index 207ac5da4dd4..230af8d7b205 100644
--- a/sound/soc/qcom/sc7280.c
+++ b/sound/soc/qcom/sc7280.c
@@ -23,6 +23,7 @@
#include "common.h"
#include "lpass.h"
#include "qdsp6/q6afe.h"
+#include "sdw.h"
#define DEFAULT_MCLK_RATE 19200000
#define RT5682_PLL_FREQ (48000 * 512)
@@ -316,6 +317,7 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
struct snd_soc_card *card = rtd->card;
struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
switch (cpu_dai->id) {
case MI2S_PRIMARY:
@@ -333,6 +335,9 @@ static void sc7280_snd_shutdown(struct snd_pcm_substream *substream)
default:
break;
}
+
+ data->sruntime[cpu_dai->id] = NULL;
+ sdw_release_stream(sruntime);
}
static int sc7280_snd_startup(struct snd_pcm_substream *substream)
@@ -347,6 +352,8 @@ static int sc7280_snd_startup(struct snd_pcm_substream *substream)
switch (cpu_dai->id) {
case MI2S_PRIMARY:
ret = sc7280_rt5682_init(rtd);
+ if (ret)
+ return ret;
break;
case SECONDARY_MI2S_RX:
codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S;
@@ -360,7 +367,8 @@ static int sc7280_snd_startup(struct snd_pcm_substream *substream)
default:
break;
}
- return ret;
+
+ return qcom_snd_sdw_startup(substream);
}
static const struct snd_soc_ops sc7280_ops = {
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c34934c31ffe..99521c784a9b 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1147,6 +1147,8 @@ static int dapm_widget_list_create(struct snd_soc_dapm_widget_list **list,
if (*list == NULL)
return -ENOMEM;
+ (*list)->num_widgets = size;
+
list_for_each_entry(w, widgets, work_list)
(*list)->widgets[i++] = w;
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index de3001f5b9bb..95d4762c9d93 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -342,11 +342,19 @@ int acp_dma_status(struct acp_dev_data *adata, unsigned char ch)
{
struct snd_sof_dev *sdev = adata->dev;
unsigned int val;
+ unsigned int acp_dma_ch_sts;
int ret = 0;
+ switch (adata->pci_rev) {
+ case ACP70_PCI_ID:
+ acp_dma_ch_sts = ACP70_DMA_CH_STS;
+ break;
+ default:
+ acp_dma_ch_sts = ACP_DMA_CH_STS;
+ }
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DMA_CNTL_0 + ch * sizeof(u32));
if (val & ACP_DMA_CH_RUN) {
- ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_DMA_CH_STS, val, !val,
+ ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, acp_dma_ch_sts, val, !val,
ACP_REG_POLL_INTERVAL,
ACP_DMA_COMPLETE_TIMEOUT_US);
if (ret < 0)
diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c
index 484c76147885..92681ca7f24d 100644
--- a/sound/soc/sof/intel/hda-dai-ops.c
+++ b/sound/soc/sof/intel/hda-dai-ops.c
@@ -346,20 +346,21 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_hdac_ext_stream_start(hext_stream);
break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- snd_hdac_ext_stream_clear(hext_stream);
-
/*
- * Save the LLP registers in case the stream is
- * restarting due PAUSE_RELEASE, or START without a pcm
- * close/open since in this case the LLP register is not reset
- * to 0 and the delay calculation will return with invalid
- * results.
+ * Save the LLP registers since in case of PAUSE the LLP
+ * register are not reset to 0, the delay calculation will use
+ * the saved offsets for compensating the delay calculation.
*/
hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
+ snd_hdac_ext_stream_clear(hext_stream);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ hext_stream->pplcllpl = 0;
+ hext_stream->pplcllpu = 0;
+ snd_hdac_ext_stream_clear(hext_stream);
break;
default:
dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
@@ -512,7 +513,6 @@ static const struct hda_dai_widget_dma_ops sdw_ipc4_chain_dma_ops = {
static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
struct snd_pcm_substream *substream, int cmd)
{
- struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream);
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
switch (cmd) {
@@ -527,9 +527,6 @@ static int hda_ipc3_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
if (ret < 0)
return ret;
- if (cmd == SNDRV_PCM_TRIGGER_STOP)
- return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
-
break;
}
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index f1a8491bba9e..ee274d445515 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -302,6 +302,7 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
}
switch (cmd) {
+ case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
ret = hda_link_dma_cleanup(substream, hext_stream, dai);
if (ret < 0) {
@@ -370,6 +371,13 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ sdev = widget_to_sdev(w);
+ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
+
+ /* nothing more to do if the link is already prepared */
+ if (hext_stream && hext_stream->link_prepared)
+ return 0;
+
/* use HDaudio stream handling */
ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags);
if (ret < 0) {
@@ -377,7 +385,6 @@ static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream,
return ret;
}
- sdev = widget_to_sdev(w);
if (sdev->dspless_mode_selected)
return 0;
@@ -482,6 +489,31 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
int ret;
int i;
+ ops = hda_dai_get_ops(substream, cpu_dai);
+ if (!ops) {
+ dev_err(cpu_dai->dev, "DAI widget ops not set\n");
+ return -EINVAL;
+ }
+
+ sdev = widget_to_sdev(w);
+ hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
+
+ /* nothing more to do if the link is already prepared */
+ if (hext_stream && hext_stream->link_prepared)
+ return 0;
+
+ /*
+ * reset the PCMSyCM registers to handle a prepare callback when the PCM is restarted
+ * due to xruns or after a call to snd_pcm_drain/drop()
+ */
+ ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
+ 0, 0, substream->stream);
+ if (ret < 0) {
+ dev_err(cpu_dai->dev, "%s: hdac_bus_eml_sdw_map_stream_ch failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
data.dai_index = (link_id << 8) | cpu_dai->id;
data.dai_node_id = intel_alh_id;
ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags);
@@ -490,10 +522,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- ops = hda_dai_get_ops(substream, cpu_dai);
- sdev = widget_to_sdev(w);
hext_stream = ops->get_hext_stream(sdev, cpu_dai, substream);
-
if (!hext_stream)
return -ENODEV;
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 624f52d2183c..b55eb977e443 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -3249,9 +3249,20 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
* group_id during copier's ipc_prepare op.
*/
if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+ struct sof_ipc4_alh_configuration_blob *blob;
+
+ blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config;
ipc4_copier->dai_index = data->dai_node_id;
- copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
- copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id);
+
+ /*
+ * no need to set the node_id for aggregated DAI's. These will be assigned
+ * a group_id during widget ipc_prepare
+ */
+ if (blob->alh_cfg.device_count == 1) {
+ copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
+ copier_data->gtw_cfg.node_id |=
+ SOF_IPC4_NODE_INDEX(data->dai_node_id);
+ }
}
break;
diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c
index 796eac0a2e74..603aed222480 100644
--- a/sound/soc/sof/sof-client-probes-ipc4.c
+++ b/sound/soc/sof/sof-client-probes-ipc4.c
@@ -125,6 +125,7 @@ static int ipc4_probes_init(struct sof_client_dev *cdev, u32 stream_tag,
msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);
msg.extension = SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(INVALID_PIPELINE_ID);
msg.extension |= SOF_IPC4_MOD_EXT_CORE_ID(0);
+ msg.extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE(sizeof(cfg) / sizeof(uint32_t));
msg.data_size = sizeof(cfg);
msg.data_ptr = &cfg;
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 27b7fdef7cb0..3efbf4aaf965 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -326,7 +326,7 @@ static int stm32_sai_get_clk_div(struct stm32_sai_sub_data *sai,
int div;
div = DIV_ROUND_CLOSEST(input_rate, output_rate);
- if (div > SAI_XCR1_MCKDIV_MAX(version)) {
+ if (div > SAI_XCR1_MCKDIV_MAX(version) || div <= 0) {
dev_err(&sai->pdev->dev, "Divider %d out of range\n", div);
return -EINVAL;
}
@@ -491,8 +491,8 @@ static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
int div;
div = stm32_sai_get_clk_div(sai, *prate, rate);
- if (div < 0)
- return div;
+ if (div <= 0)
+ return -EINVAL;
mclk->freq = *prate / div;
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index d1b32ba1e1a2..9e30852de93c 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -939,7 +939,7 @@ static void stm32_spdifrx_remove(struct platform_device *pdev)
{
struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev);
- if (spdifrx->ctrl_chan)
+ if (!IS_ERR(spdifrx->ctrl_chan))
dma_release_channel(spdifrx->ctrl_chan);
if (spdifrx->dmab)