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/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e103bb3693c0..3c629f4ae080 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9260,6 +9260,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0ac9, "Dell Precision 3260", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), @@ -11617,6 +11618,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), + SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB), SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB), SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2), SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2), diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 9a30f6d35d13..24b978234000 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c @@ -1892,13 +1892,10 @@ static int aureon_add_controls(struct snd_ice1712 *ice) unsigned char id; snd_ice1712_save_gpio_status(ice); id = aureon_cs8415_get(ice, CS8415_ID); + snd_ice1712_restore_gpio_status(ice); if (id != 0x41) dev_info(ice->card->dev, "No CS8415 chip. Skipping CS8415 controls.\n"); - else if ((id & 0x0F) != 0x01) - dev_info(ice->card->dev, - "Detected unsupported CS8415 rev. (%c)\n", - (char)((id & 0x0F) + 'A' - 1)); else { for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) { struct snd_kcontrol *kctl; @@ -1909,7 +1906,6 @@ static int aureon_add_controls(struct snd_ice1712 *ice) kctl->id.device = ice->pcm->device; } } - snd_ice1712_restore_gpio_status(ice); } return 0; 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 +#include #include #include #include @@ -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 @@ -223,6 +223,20 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_RT5682_SSP_AMP(2) | SOF_RT5682_NUM_HDMIDEV(4)), }, + { + .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 = { @@ -1105,6 +1119,15 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_AMP(1) | 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 | 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, ®_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_dai_trigger(substream, cmd, 0); + 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); + } start_err: if (ret < 0) rollback = 1;