summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/apple,mca.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml6
-rw-r--r--include/sound/soc-component.h2
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c14
-rw-r--r--sound/soc/apple/mca.c31
-rw-r--r--sound/soc/atmel/mchp-pdmc.c53
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c3
-rw-r--r--sound/soc/codecs/Kconfig1
-rw-r--r--sound/soc/codecs/adau7118.c19
-rw-r--r--sound/soc/codecs/da7219-aad.c41
-rw-r--r--sound/soc/codecs/da7219-aad.h4
-rw-r--r--sound/soc/codecs/mt6358.c11
-rw-r--r--sound/soc/codecs/sma1303.c2
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c23
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c12
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-dai-i2s.c21
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-dai-etdm.c11
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-dai-adda.c58
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-etdm.c3
-rw-r--r--sound/soc/sh/rcar/adg.c64
-rw-r--r--sound/soc/soc-pcm.c27
21 files changed, 260 insertions, 147 deletions
diff --git a/Documentation/devicetree/bindings/sound/apple,mca.yaml b/Documentation/devicetree/bindings/sound/apple,mca.yaml
index 40e3a202f443..5c6ec08c7d24 100644
--- a/Documentation/devicetree/bindings/sound/apple,mca.yaml
+++ b/Documentation/devicetree/bindings/sound/apple,mca.yaml
@@ -23,6 +23,7 @@ properties:
- enum:
- apple,t6000-mca
- apple,t8103-mca
+ - apple,t8112-mca
- const: apple,mca
reg:
diff --git a/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml b/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml
index c4cf1e5ab84b..9b40268537cb 100644
--- a/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml
+++ b/Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml
@@ -67,6 +67,12 @@ properties:
maxItems: 4
uniqueItems: true
+ microchip,startup-delay-us:
+ description: |
+ Specifies the delay in microseconds that needs to be applied after
+ enabling the PDMC microphones to avoid unwanted noise due to microphones
+ not being ready.
+
required:
- compatible
- reg
diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h
index 3203d35bc8c1..0814ed143864 100644
--- a/include/sound/soc-component.h
+++ b/include/sound/soc-component.h
@@ -190,6 +190,8 @@ struct snd_soc_component_driver {
bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */
int be_pcm_base; /* base device ID for all BE PCMs */
+ unsigned int start_dma_last;
+
#ifdef CONFIG_DEBUG_FS
const char *debugfs_prefix;
#endif
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 36314753923b..4a69ce702360 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -255,6 +255,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "15NBC1011"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "OMEN by HP Gaming Laptop 16z-n000"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8A43"),
+ }
+ },
{}
};
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index 24381c42eb54..64750db9b963 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -101,7 +101,6 @@
#define SERDES_CONF_UNK3 BIT(14)
#define SERDES_CONF_NO_DATA_FEEDBACK BIT(15)
#define SERDES_CONF_SYNC_SEL GENMASK(18, 16)
-#define SERDES_CONF_SOME_RST BIT(19)
#define REG_TX_SERDES_BITSTART 0x08
#define REG_RX_SERDES_BITSTART 0x0c
#define REG_TX_SERDES_SLOTMASK 0x0c
@@ -203,15 +202,24 @@ static void mca_fe_early_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
+ FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
+ mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
+ FIELD_PREP(SERDES_CONF_SYNC_SEL, 7));
mca_modify(cl, serdes_unit + REG_SERDES_STATUS,
SERDES_STATUS_EN | SERDES_STATUS_RST,
SERDES_STATUS_RST);
- mca_modify(cl, serdes_conf, SERDES_CONF_SOME_RST,
- SERDES_CONF_SOME_RST);
- readl_relaxed(cl->base + serdes_conf);
- mca_modify(cl, serdes_conf, SERDES_STATUS_RST, 0);
- WARN_ON(readl_relaxed(cl->base + REG_SERDES_STATUS) &
+ /*
+ * Experiments suggest that it takes at most ~1 us
+ * for the bit to clear, so wait 2 us for good measure.
+ */
+ udelay(2);
+ WARN_ON(readl_relaxed(cl->base + serdes_unit + REG_SERDES_STATUS) &
SERDES_STATUS_RST);
+ mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
+ FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
+ mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
+ FIELD_PREP(SERDES_CONF_SYNC_SEL, cl->no + 1));
break;
default:
break;
@@ -942,10 +950,17 @@ static int mca_pcm_new(struct snd_soc_component *component,
chan = mca_request_dma_channel(cl, i);
if (IS_ERR_OR_NULL(chan)) {
+ mca_pcm_free(component, rtd->pcm);
+
+ if (chan && PTR_ERR(chan) == -EPROBE_DEFER)
+ return PTR_ERR(chan);
+
dev_err(component->dev, "unable to obtain DMA channel (stream %d cluster %d): %pe\n",
i, cl->no, chan);
- mca_pcm_free(component, rtd->pcm);
- return -EINVAL;
+
+ if (!chan)
+ return -EINVAL;
+ return PTR_ERR(chan);
}
cl->dma_chans[i] = chan;
diff --git a/sound/soc/atmel/mchp-pdmc.c b/sound/soc/atmel/mchp-pdmc.c
index cf4084dcbd5e..1aed3baa9369 100644
--- a/sound/soc/atmel/mchp-pdmc.c
+++ b/sound/soc/atmel/mchp-pdmc.c
@@ -114,6 +114,7 @@ struct mchp_pdmc {
struct clk *gclk;
u32 pdmcen;
u32 suspend_irq;
+ u32 startup_delay_us;
int mic_no;
int sinc_order;
bool audio_filter_en;
@@ -425,6 +426,7 @@ static const struct snd_soc_component_driver mchp_pdmc_dai_component = {
.open = &mchp_pdmc_open,
.close = &mchp_pdmc_close,
.legacy_dai_naming = 1,
+ .start_dma_last = 1,
};
static const unsigned int mchp_pdmc_1mic[] = {1};
@@ -632,6 +634,29 @@ static int mchp_pdmc_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static void mchp_pdmc_noise_filter_workaround(struct mchp_pdmc *dd)
+{
+ u32 tmp, steps = 16;
+
+ /*
+ * PDMC doesn't wait for microphones' startup time thus the acquisition
+ * may start before the microphones are ready leading to poc noises at
+ * the beginning of capture. To avoid this, we need to wait 50ms (in
+ * normal startup procedure) or 150 ms (worst case after resume from sleep
+ * states) after microphones are enabled and then clear the FIFOs (by
+ * reading the RHR 16 times) and possible interrupts before continuing.
+ * Also, for this to work the DMA needs to be started after interrupts
+ * are enabled.
+ */
+ usleep_range(dd->startup_delay_us, dd->startup_delay_us + 5);
+
+ while (steps--)
+ regmap_read(dd->regmap, MCHP_PDMC_RHR, &tmp);
+
+ /* Clear interrupts. */
+ regmap_read(dd->regmap, MCHP_PDMC_ISR, &tmp);
+}
+
static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
@@ -644,15 +669,17 @@ static int mchp_pdmc_trigger(struct snd_pcm_substream *substream,
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_START:
- /* Enable overrun and underrun error interrupts */
- regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq |
- MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR);
- dd->suspend_irq = 0;
- fallthrough;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
snd_soc_component_update_bits(cpu, MCHP_PDMC_MR,
MCHP_PDMC_MR_PDMCEN_MASK,
dd->pdmcen);
+
+ mchp_pdmc_noise_filter_workaround(dd);
+
+ /* Enable interrupts. */
+ regmap_write(dd->regmap, MCHP_PDMC_IER, dd->suspend_irq |
+ MCHP_PDMC_IR_RXOVR | MCHP_PDMC_IR_RXUDR);
+ dd->suspend_irq = 0;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
regmap_read(dd->regmap, MCHP_PDMC_IMR, &dd->suspend_irq);
@@ -796,6 +823,7 @@ static bool mchp_pdmc_readable_reg(struct device *dev, unsigned int reg)
case MCHP_PDMC_CFGR:
case MCHP_PDMC_IMR:
case MCHP_PDMC_ISR:
+ case MCHP_PDMC_RHR:
case MCHP_PDMC_VER:
return true;
default:
@@ -817,6 +845,17 @@ static bool mchp_pdmc_writeable_reg(struct device *dev, unsigned int reg)
}
}
+static bool mchp_pdmc_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case MCHP_PDMC_ISR:
+ case MCHP_PDMC_RHR:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool mchp_pdmc_precious_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -836,6 +875,7 @@ static const struct regmap_config mchp_pdmc_regmap_config = {
.readable_reg = mchp_pdmc_readable_reg,
.writeable_reg = mchp_pdmc_writeable_reg,
.precious_reg = mchp_pdmc_precious_reg,
+ .volatile_reg = mchp_pdmc_volatile_reg,
.cache_type = REGCACHE_FLAT,
};
@@ -918,6 +958,9 @@ static int mchp_pdmc_dt_init(struct mchp_pdmc *dd)
dd->channel_mic_map[i].clk_edge = edge;
}
+ dd->startup_delay_us = 150000;
+ of_property_read_u32(np, "microchip,startup-delay-us", &dd->startup_delay_us);
+
return 0;
}
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 1430642c8433..785b9d01d8af 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -98,6 +98,9 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = {
.init = at91sam9g20ek_wm8731_init,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBP_CFP,
+#ifndef ENABLE_MIC_INPUT
+ .playback_only = true,
+#endif
SND_SOC_DAILINK_REG(pcm),
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bd72c426a93d..07747565c3b5 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -2103,6 +2103,7 @@ config SND_SOC_WSA883X
config SND_SOC_ZL38060
tristate "Microsemi ZL38060 Connected Home Audio Processor"
depends on SPI_MASTER
+ depends on GPIOLIB
select REGMAP
help
Support for ZL38060 Connected Home Audio Processor from Microsemi,
diff --git a/sound/soc/codecs/adau7118.c b/sound/soc/codecs/adau7118.c
index bbb097249887..a663d37e5776 100644
--- a/sound/soc/codecs/adau7118.c
+++ b/sound/soc/codecs/adau7118.c
@@ -444,22 +444,6 @@ static const struct snd_soc_component_driver adau7118_component_driver = {
.endianness = 1,
};
-static void adau7118_regulator_disable(void *data)
-{
- struct adau7118_data *st = data;
- int ret;
- /*
- * If we fail to disable DVDD, don't bother in trying IOVDD. We
- * actually don't want to be left in the situation where DVDD
- * is enabled and IOVDD is disabled.
- */
- ret = regulator_disable(st->dvdd);
- if (ret)
- return;
-
- regulator_disable(st->iovdd);
-}
-
static int adau7118_regulator_setup(struct adau7118_data *st)
{
st->iovdd = devm_regulator_get(st->dev, "iovdd");
@@ -481,8 +465,7 @@ static int adau7118_regulator_setup(struct adau7118_data *st)
regcache_cache_only(st->map, true);
}
- return devm_add_action_or_reset(st->dev, adau7118_regulator_disable,
- st);
+ return 0;
}
static int adau7118_parset_dt(const struct adau7118_data *st)
diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c
index c55b033d89da..4a4f09f924bc 100644
--- a/sound/soc/codecs/da7219-aad.c
+++ b/sound/soc/codecs/da7219-aad.c
@@ -339,11 +339,39 @@ static void da7219_aad_hptest_work(struct work_struct *work)
SND_JACK_HEADSET | SND_JACK_LINEOUT);
}
+static void da7219_aad_jack_det_work(struct work_struct *work)
+{
+ struct da7219_aad_priv *da7219_aad =
+ container_of(work, struct da7219_aad_priv, jack_det_work);
+ struct snd_soc_component *component = da7219_aad->component;
+ u8 srm_st;
+
+ mutex_lock(&da7219_aad->jack_det_mutex);
+
+ srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK;
+ msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4);
+ /* Enable ground switch */
+ snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);
+
+ mutex_unlock(&da7219_aad->jack_det_mutex);
+}
+
/*
* IRQ
*/
+static irqreturn_t da7219_aad_pre_irq_thread(int irq, void *data)
+{
+
+ struct da7219_aad_priv *da7219_aad = data;
+
+ if (!da7219_aad->jack_inserted)
+ schedule_work(&da7219_aad->jack_det_work);
+
+ return IRQ_WAKE_THREAD;
+}
+
static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
{
struct da7219_aad_priv *da7219_aad = data;
@@ -351,14 +379,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
u8 events[DA7219_AAD_IRQ_REG_MAX];
- u8 statusa, srm_st;
+ u8 statusa;
int i, report = 0, mask = 0;
- srm_st = snd_soc_component_read(component, DA7219_PLL_SRM_STS) & DA7219_PLL_SRM_STS_MCLK;
- msleep(da7219_aad->gnd_switch_delay * ((srm_st == 0x0) ? 2 : 1) - 4);
- /* Enable ground switch */
- snd_soc_component_update_bits(component, 0xFB, 0x01, 0x01);
-
/* Read current IRQ events */
regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
events, DA7219_AAD_IRQ_REG_MAX);
@@ -377,6 +400,9 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B],
statusa);
+ if (!da7219_aad->jack_inserted)
+ cancel_work_sync(&da7219_aad->jack_det_work);
+
if (statusa & DA7219_JACK_INSERTION_STS_MASK) {
/* Jack Insertion */
if (events[DA7219_AAD_IRQ_REG_A] &
@@ -940,8 +966,9 @@ int da7219_aad_init(struct snd_soc_component *component)
INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work);
INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
+ INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work);
- ret = request_threaded_irq(da7219_aad->irq, NULL,
+ ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread,
da7219_aad_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"da7219-aad", da7219_aad);
diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h
index 21fdf53095cc..be87ee47edde 100644
--- a/sound/soc/codecs/da7219-aad.h
+++ b/sound/soc/codecs/da7219-aad.h
@@ -11,6 +11,7 @@
#define __DA7219_AAD_H
#include <linux/timer.h>
+#include <linux/mutex.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include <sound/da7219-aad.h>
@@ -196,6 +197,9 @@ struct da7219_aad_priv {
struct work_struct btn_det_work;
struct work_struct hptest_work;
+ struct work_struct jack_det_work;
+
+ struct mutex jack_det_mutex;
struct snd_soc_jack *jack;
bool micbias_resume_enable;
diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c
index 93f35e8d26fc..b54610b27906 100644
--- a/sound/soc/codecs/mt6358.c
+++ b/sound/soc/codecs/mt6358.c
@@ -560,6 +560,9 @@ static int mt6358_put_wov(struct snd_kcontrol *kcontrol,
struct mt6358_priv *priv = snd_soc_component_get_drvdata(c);
int enabled = ucontrol->value.integer.value[0];
+ if (enabled < 0 || enabled > 1)
+ return -EINVAL;
+
if (priv->wov_enabled != enabled) {
if (enabled)
mt6358_enable_wov_phase2(priv);
@@ -567,6 +570,8 @@ static int mt6358_put_wov(struct snd_kcontrol *kcontrol,
mt6358_disable_wov_phase2(priv);
priv->wov_enabled = enabled;
+
+ return 1;
}
return 0;
@@ -632,9 +637,6 @@ static const char * const hp_in_mux_map[] = {
"Audio Playback",
"Test Mode",
"HP Impedance",
- "undefined1",
- "undefined2",
- "undefined3",
};
static int hp_in_mux_map_value[] = {
@@ -643,9 +645,6 @@ static int hp_in_mux_map_value[] = {
HP_MUX_HP,
HP_MUX_TEST_MODE,
HP_MUX_HP_IMPEDANCE,
- HP_MUX_OPEN,
- HP_MUX_OPEN,
- HP_MUX_OPEN,
};
static SOC_VALUE_ENUM_SINGLE_DECL(hpl_in_mux_map_enum,
diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c
index 727c01facf52..fa4b0a60f8a9 100644
--- a/sound/soc/codecs/sma1303.c
+++ b/sound/soc/codecs/sma1303.c
@@ -569,7 +569,7 @@ static int sma1303_aif_in_event(struct snd_soc_dapm_widget *w,
ret += sma1303_regmap_update_bits(sma1303,
SMA1303_11_SYSTEM_CTRL2,
SMA1303_LR_DATA_SW_MASK,
- SMA1303_LR_DATA_SW_NORMAL,
+ SMA1303_LR_DATA_SW_SWAP,
&temp);
if (temp == true)
change = true;
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 71a11d747622..4fe448295a90 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -227,6 +227,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
.callback = sof_rt5682_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
+ DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S"),
+ },
+ .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+ SOF_RT5682_SSP_CODEC(2) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_MAX98360A_SPEAKER_AMP_PRESENT |
+ SOF_RT5682_SSP_AMP(0) |
+ SOF_RT5682_NUM_HDMIDEV(4)
+ ),
+ },
+ {
+ .callback = sof_rt5682_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
},
.driver_data = (void *)(SOF_RT5682_MCLK_EN |
SOF_RT5682_SSP_CODEC(2) |
@@ -1106,6 +1120,15 @@ static const struct platform_device_id board_ids[] = {
SOF_RT5682_NUM_HDMIDEV(4)),
},
{
+ .name = "mtl_mx98360_rt5682",
+ .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
+ SOF_RT5682_SSP_CODEC(0) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_MAX98360A_SPEAKER_AMP_PRESENT |
+ SOF_RT5682_SSP_AMP(1) |
+ SOF_RT5682_NUM_HDMIDEV(4)),
+ },
+ {
.name = "jsl_rt5682",
.driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN |
SOF_RT5682_MCLK_24MHZ |
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index b1a66a0f6818..7911c3af8071 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -15,6 +15,11 @@ static const struct snd_soc_acpi_codecs mtl_max98357a_amp = {
.codecs = {"MX98357A"}
};
+static const struct snd_soc_acpi_codecs mtl_max98360a_amp = {
+ .num_codecs = 1,
+ .codecs = {"MX98360A"}
+};
+
static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = {
.num_codecs = 2,
.codecs = {"10EC5682", "RTL5682"},
@@ -28,6 +33,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = {
.quirk_data = &mtl_max98357a_amp,
.sof_tplg_filename = "sof-mtl-max98357a-rt5682.tplg",
},
+ {
+ .comp_ids = &mtl_rt5682_rt5682s_hp,
+ .drv_name = "mtl_mx98360_rt5682",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &mtl_max98360a_amp,
+ .sof_tplg_filename = "sof-mtl-max98360a-rt5682.tplg",
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines);
diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
index 6a9ace4180d3..8645ab686970 100644
--- a/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
+++ b/sound/soc/mediatek/mt8183/mt8183-dai-i2s.c
@@ -141,16 +141,13 @@ static int mt8183_i2s_hd_set(struct snd_kcontrol *kcontrol,
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- int hd_en;
+ int hd_en, change;
if (ucontrol->value.enumerated.item[0] >= e->items)
return -EINVAL;
hd_en = ucontrol->value.integer.value[0];
- dev_info(afe->dev, "%s(), kcontrol name %s, hd_en %d\n",
- __func__, kcontrol->id.name, hd_en);
-
i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name);
if (!i2s_priv) {
@@ -158,9 +155,10 @@ static int mt8183_i2s_hd_set(struct snd_kcontrol *kcontrol,
return -EINVAL;
}
+ change = i2s_priv->low_jitter_en != hd_en;
i2s_priv->low_jitter_en = hd_en;
- return 0;
+ return change;
}
static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {
@@ -276,9 +274,6 @@ static int mtk_apll_event(struct snd_soc_dapm_widget *w,
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
- dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
- __func__, w->name, event);
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
if (strcmp(w->name, APLL1_W_NAME) == 0)
@@ -307,9 +302,6 @@ static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mtk_afe_i2s_priv *i2s_priv;
- dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
- __func__, w->name, event);
-
i2s_priv = get_i2s_priv_by_name(afe, w->name);
if (!i2s_priv) {
@@ -715,11 +707,6 @@ static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
unsigned int i2s_con = 0, fmt_con = I2S_FMT_I2S << I2S_FMT_SFT;
int ret = 0;
- dev_info(afe->dev, "%s(), id %d, rate %d, format %d\n",
- __func__,
- i2s_id,
- rate, format);
-
if (i2s_priv) {
i2s_priv->rate = rate;
@@ -810,8 +797,6 @@ static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
return -EINVAL;
}
- dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
-
apll = mt8183_get_apll_by_rate(afe, freq);
apll_rate = mt8183_get_apll_rate(afe, apll);
diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
index 071841903c62..7a37752d4244 100644
--- a/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
+++ b/sound/soc/mediatek/mt8188/mt8188-dai-etdm.c
@@ -679,7 +679,6 @@ static int mt8188_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol,
unsigned int old_val;
unsigned int mask;
unsigned int reg;
- unsigned int shift;
if (source >= e->items)
return -EINVAL;
@@ -687,27 +686,22 @@ static int mt8188_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol,
if (!strcmp(kcontrol->id.name, "ETDM_OUT1_Clock_Source")) {
reg = ETDM_OUT1_CON4;
mask = ETDM_OUT_CON4_CLOCK_MASK;
- shift = ETDM_OUT_CON4_CLOCK_SHIFT;
val = FIELD_PREP(ETDM_OUT_CON4_CLOCK_MASK, source);
} else if (!strcmp(kcontrol->id.name, "ETDM_OUT2_Clock_Source")) {
reg = ETDM_OUT2_CON4;
mask = ETDM_OUT_CON4_CLOCK_MASK;
- shift = ETDM_OUT_CON4_CLOCK_SHIFT;
val = FIELD_PREP(ETDM_OUT_CON4_CLOCK_MASK, source);
} else if (!strcmp(kcontrol->id.name, "ETDM_OUT3_Clock_Source")) {
reg = ETDM_OUT3_CON4;
mask = ETDM_OUT_CON4_CLOCK_MASK;
- shift = ETDM_OUT_CON4_CLOCK_SHIFT;
val = FIELD_PREP(ETDM_OUT_CON4_CLOCK_MASK, source);
} else if (!strcmp(kcontrol->id.name, "ETDM_IN1_Clock_Source")) {
reg = ETDM_IN1_CON2;
mask = ETDM_IN_CON2_CLOCK_MASK;
- shift = ETDM_IN_CON2_CLOCK_SHIFT;
val = FIELD_PREP(ETDM_IN_CON2_CLOCK_MASK, source);
} else if (!strcmp(kcontrol->id.name, "ETDM_IN2_Clock_Source")) {
reg = ETDM_IN2_CON2;
mask = ETDM_IN_CON2_CLOCK_MASK;
- shift = ETDM_IN_CON2_CLOCK_SHIFT;
val = FIELD_PREP(ETDM_IN_CON2_CLOCK_MASK, source);
} else {
return -EINVAL;
@@ -715,8 +709,6 @@ static int mt8188_etdm_clk_src_sel_put(struct snd_kcontrol *kcontrol,
regmap_read(afe->regmap, reg, &old_val);
old_val &= mask;
- old_val >>= shift;
-
if (old_val == val)
return 0;
@@ -2506,6 +2498,9 @@ static void mt8188_dai_etdm_parse_of(struct mtk_base_afe *afe)
/* etdm in only */
for (i = 0; i < 2; i++) {
+ dai_id = ETDM_TO_DAI_ID(i);
+ etdm_data = afe_priv->dai_priv[dai_id];
+
snprintf(prop, sizeof(prop), "mediatek,%s-chn-disabled",
of_afe_etdms[i].name);
diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-adda.c b/sound/soc/mediatek/mt8192/mt8192-dai-adda.c
index f8c73e8624df..4919535e2759 100644
--- a/sound/soc/mediatek/mt8192/mt8192-dai-adda.c
+++ b/sound/soc/mediatek/mt8192/mt8192-dai-adda.c
@@ -303,9 +303,6 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int mtkaif_dmic = afe_priv->mtkaif_dmic;
- dev_info(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n",
- __func__, w->name, event, mtkaif_dmic);
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 1);
@@ -345,10 +342,6 @@ static int mtk_adda_ch34_ul_event(struct snd_soc_dapm_widget *w,
int mtkaif_dmic = afe_priv->mtkaif_dmic_ch34;
int mtkaif_adda6_only = afe_priv->mtkaif_adda6_only;
- dev_info(afe->dev,
- "%s(), name %s, event 0x%x, mtkaif_dmic %d, mtkaif_adda6_only %d\n",
- __func__, w->name, event, mtkaif_dmic, mtkaif_adda6_only);
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34,
@@ -538,9 +531,6 @@ static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w,
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
- dev_info(afe->dev, "%s(), name %s, event 0x%x\n",
- __func__, w->name, event);
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA, 0);
@@ -564,9 +554,6 @@ static int mtk_adda_ch34_dl_event(struct snd_soc_dapm_widget *w,
struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
- dev_info(afe->dev, "%s(), name %s, event 0x%x\n",
- __func__, w->name, event);
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
mt8192_afe_gpio_request(afe->dev, true, MT8192_DAI_ADDA_CH34,
@@ -604,19 +591,21 @@ static int stf_positive_gain_set(struct snd_kcontrol *kcontrol,
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int gain_db = ucontrol->value.integer.value[0];
+ bool change = false;
afe_priv->stf_positive_gain_db = gain_db;
if (gain_db >= 0 && gain_db <= 24) {
- regmap_update_bits(afe->regmap,
- AFE_SIDETONE_GAIN,
- POSITIVE_GAIN_MASK_SFT,
- (gain_db / 6) << POSITIVE_GAIN_SFT);
+ regmap_update_bits_check(afe->regmap,
+ AFE_SIDETONE_GAIN,
+ POSITIVE_GAIN_MASK_SFT,
+ (gain_db / 6) << POSITIVE_GAIN_SFT,
+ &change);
} else {
- dev_warn(afe->dev, "%s(), gain_db %d invalid\n",
- __func__, gain_db);
+ return -EINVAL;
}
- return 0;
+
+ return change;
}
static int mt8192_adda_dmic_get(struct snd_kcontrol *kcontrol,
@@ -637,15 +626,17 @@ static int mt8192_adda_dmic_set(struct snd_kcontrol *kcontrol,
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int dmic_on;
+ bool change;
dmic_on = ucontrol->value.integer.value[0];
- dev_info(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n",
- __func__, kcontrol->id.name, dmic_on);
+ change = (afe_priv->mtkaif_dmic != dmic_on) ||
+ (afe_priv->mtkaif_dmic_ch34 != dmic_on);
afe_priv->mtkaif_dmic = dmic_on;
afe_priv->mtkaif_dmic_ch34 = dmic_on;
- return 0;
+
+ return change;
}
static int mt8192_adda6_only_get(struct snd_kcontrol *kcontrol,
@@ -666,20 +657,20 @@ static int mt8192_adda6_only_set(struct snd_kcontrol *kcontrol,
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
struct mt8192_afe_private *afe_priv = afe->platform_priv;
int mtkaif_adda6_only;
+ bool change;
mtkaif_adda6_only = ucontrol->value.integer.value[0];
- dev_info(afe->dev, "%s(), kcontrol name %s, mtkaif_adda6_only %d\n",
- __func__, kcontrol->id.name, mtkaif_adda6_only);
-
+ change = afe_priv->mtkaif_adda6_only != mtkaif_adda6_only;
afe_priv->mtkaif_adda6_only = mtkaif_adda6_only;
- return 0;
+
+ return change;
}
static const struct snd_kcontrol_new mtk_adda_controls[] = {
SOC_SINGLE("Sidetone_Gain", AFE_SIDETONE_GAIN,
SIDE_TONE_GAIN_SFT, SIDE_TONE_GAIN_MASK, 0),
- SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 100, 0,
+ SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 24, 0,
stf_positive_gain_get, stf_positive_gain_set),
SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1,
DL_2_GAIN_CTL_PRE_SFT, DL_2_GAIN_CTL_PRE_MASK, 0),
@@ -750,9 +741,6 @@ static int mtk_stf_event(struct snd_soc_dapm_widget *w,
regmap_read(afe->regmap, AFE_SIDETONE_CON1, &reg_value);
- dev_info(afe->dev, "%s(), name %s, event 0x%x, ul_rate 0x%x, AFE_SIDETONE_CON1 0x%x\n",
- __func__, w->name, event, ul_rate, reg_value);
-
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* set side tone gain = 0 */
@@ -1163,12 +1151,6 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
unsigned int rate = params_rate(params);
int id = dai->id;
- dev_info(afe->dev, "%s(), id %d, stream %d, rate %d\n",
- __func__,
- id,
- substream->stream,
- rate);
-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
unsigned int dl_src2_con0 = 0;
unsigned int dl_src2_con1 = 0;
@@ -1441,8 +1423,6 @@ int mt8192_dai_adda_register(struct mtk_base_afe *afe)
struct mtk_base_afe_dai *dai;
struct mt8192_afe_private *afe_priv = afe->platform_priv;
- dev_info(afe->dev, "%s()\n", __func__);
-
dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
if (!dai)
return -ENOMEM;
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
index c2e268054773..f2c9a1fdbe0d 100644
--- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
@@ -2567,6 +2567,9 @@ static void mt8195_dai_etdm_parse_of(struct mtk_base_afe *afe)
/* etdm in only */
for (i = 0; i < 2; i++) {
+ dai_id = ETDM_TO_DAI_ID(i);
+ etdm_data = afe_priv->dai_priv[dai_id];
+
ret = snprintf(prop, sizeof(prop),
"mediatek,%s-chn-disabled",
of_afe_etdms[i].name);
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index 7bc4421835d7..0b8926600d90 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -39,10 +39,10 @@ struct rsnd_adg {
int clkin_size;
int clkout_size;
u32 ckr;
- u32 rbga;
- u32 rbgb;
+ u32 brga;
+ u32 brgb;
- int rbg_rate[ADG_HZ_SIZE]; /* RBGA / RBGB */
+ int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */
};
#define for_each_rsnd_clkin(pos, adg, i) \
@@ -75,7 +75,7 @@ static const char * const clkout_name_gen2[] = {
[CLKOUT3] = "audio_clkout3",
};
-static u32 rsnd_adg_calculate_rbgx(unsigned long div)
+static u32 rsnd_adg_calculate_brgx(unsigned long div)
{
int i;
@@ -131,8 +131,8 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
adg->clkin_rate[CLKA], /* 0000: CLKA */
adg->clkin_rate[CLKB], /* 0001: CLKB */
adg->clkin_rate[CLKC], /* 0010: CLKC */
- adg->rbg_rate[ADG_HZ_441], /* 0011: RBGA */
- adg->rbg_rate[ADG_HZ_48], /* 0100: RBGB */
+ adg->brg_rate[ADG_HZ_441], /* 0011: BRGA */
+ adg->brg_rate[ADG_HZ_48], /* 0100: BRGB */
};
min = ~0;
@@ -323,10 +323,10 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
/*
* find divided clock from BRGA/BRGB
*/
- if (rate == adg->rbg_rate[ADG_HZ_441])
+ if (rate == adg->brg_rate[ADG_HZ_441])
return 0x10;
- if (rate == adg->rbg_rate[ADG_HZ_48])
+ if (rate == adg->brg_rate[ADG_HZ_48])
return 0x20;
return -EIO;
@@ -358,13 +358,13 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
ckr = 0x80000000; /* BRGB output = 48kHz */
rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr);
- rsnd_mod_write(adg_mod, BRRA, adg->rbga);
- rsnd_mod_write(adg_mod, BRRB, adg->rbgb);
+ rsnd_mod_write(adg_mod, BRRA, adg->brga);
+ rsnd_mod_write(adg_mod, BRRB, adg->brgb);
dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n",
(ckr) ? 'B' : 'A',
- (ckr) ? adg->rbg_rate[ADG_HZ_48] :
- adg->rbg_rate[ADG_HZ_441]);
+ (ckr) ? adg->brg_rate[ADG_HZ_48] :
+ adg->brg_rate[ADG_HZ_441]);
return 0;
}
@@ -484,7 +484,7 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
struct property *prop;
- u32 ckr, rbgx, rbga, rbgb;
+ u32 ckr, brgx, brga, brgb;
u32 rate, div;
u32 req_rate[ADG_HZ_SIZE] = {};
uint32_t count = 0;
@@ -501,8 +501,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
};
ckr = 0;
- rbga = 2; /* default 1/6 */
- rbgb = 2; /* default 1/6 */
+ brga = 2; /* default 1/6 */
+ brgb = 2; /* default 1/6 */
/*
* ADG supports BRRA/BRRB output only
@@ -543,30 +543,30 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
if (0 == rate) /* not used */
continue;
- /* RBGA */
- if (!adg->rbg_rate[ADG_HZ_441] && (0 == rate % 44100)) {
+ /* BRGA */
+ if (!adg->brg_rate[ADG_HZ_441] && (0 == rate % 44100)) {
div = 6;
if (req_Hz[ADG_HZ_441])
div = rate / req_Hz[ADG_HZ_441];
- rbgx = rsnd_adg_calculate_rbgx(div);
- if (BRRx_MASK(rbgx) == rbgx) {
- rbga = rbgx;
- adg->rbg_rate[ADG_HZ_441] = rate / div;
+ brgx = rsnd_adg_calculate_brgx(div);
+ if (BRRx_MASK(brgx) == brgx) {
+ brga = brgx;
+ adg->brg_rate[ADG_HZ_441] = rate / div;
ckr |= brg_table[i] << 20;
if (req_Hz[ADG_HZ_441])
parent_clk_name = __clk_get_name(clk);
}
}
- /* RBGB */
- if (!adg->rbg_rate[ADG_HZ_48] && (0 == rate % 48000)) {
+ /* BRGB */
+ if (!adg->brg_rate[ADG_HZ_48] && (0 == rate % 48000)) {
div = 6;
if (req_Hz[ADG_HZ_48])
div = rate / req_Hz[ADG_HZ_48];
- rbgx = rsnd_adg_calculate_rbgx(div);
- if (BRRx_MASK(rbgx) == rbgx) {
- rbgb = rbgx;
- adg->rbg_rate[ADG_HZ_48] = rate / div;
+ brgx = rsnd_adg_calculate_brgx(div);
+ if (BRRx_MASK(brgx) == brgx) {
+ brgb = brgx;
+ adg->brg_rate[ADG_HZ_48] = rate / div;
ckr |= brg_table[i] << 16;
if (req_Hz[ADG_HZ_48])
parent_clk_name = __clk_get_name(clk);
@@ -620,8 +620,8 @@ static int rsnd_adg_get_clkout(struct rsnd_priv *priv)
rsnd_adg_get_clkout_end:
adg->ckr = ckr;
- adg->rbga = rbga;
- adg->rbgb = rbgb;
+ adg->brga = brga;
+ adg->brgb = brgb;
return 0;
@@ -663,9 +663,9 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)
__clk_get_name(clk), clk, clk_get_rate(clk));
dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n",
- adg->ckr, adg->rbga, adg->rbgb);
- dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->rbg_rate[ADG_HZ_441]);
- dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->rbg_rate[ADG_HZ_48]);
+ adg->ckr, adg->brga, adg->brgb);
+ dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]);
+ dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]);
/*
* Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start()
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 005b179a770a..5eb056b942ce 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1088,22 +1088,39 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
- int ret = -EINVAL, _ret = 0;
+ struct snd_soc_component *component;
+ int ret = -EINVAL, _ret = 0, start_dma_last = 0, i;
int rollback = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /* Do we need to start dma last? */
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->start_dma_last) {
+ start_dma_last = 1;
+ break;
+ }
+ }
+
ret = snd_soc_link_trigger(substream, cmd, 0);
if (ret < 0)
goto start_err;
- ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
- if (ret < 0)
- goto start_err;
+ if (start_dma_last) {
+ ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
+ if (ret < 0)
+ goto start_err;
+
+ ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
+ } else {
+ ret = snd_soc_pcm_component_trigger(substream, cmd, 0);
+ if (ret < 0)
+ goto start_err;
- ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
+ ret = snd_soc_pcm_dai_trigger(substream, cmd, 0);
+ }
start_err:
if (ret < 0)
rollback = 1;