diff options
author | Takashi Iwai | 2023-03-03 14:21:13 +0100 |
---|---|---|
committer | Takashi Iwai | 2023-03-03 14:21:13 +0100 |
commit | fb2e5fc8c8d9d5f95c7a2e1ed6f45b2b3ba836a8 (patch) | |
tree | 636387e1c12bfe74304e6d56b445f94f50b10466 | |
parent | 26ed1d29fc44f3f2f0c396c1392abefac5f0454e (diff) | |
parent | b56ec2992a2e43bc3e60d6db86849d31640e791f (diff) |
Merge tag 'asoc-fix-v6.3' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v6.3
Almost all of this is driver specific fixes and new IDs that have come
in during the merge window. A good chunk of them are simple ones from
me which came about due to a bunch of Mediatek Chromebooks being enabled
in KernelCI, there's more where that came from.
We do have one small feature added to the PCM core by Claudiu Beznea in
order to allow the sequencing required to resolve a noise issue with the
Microchip PDMC driver.
-rw-r--r-- | Documentation/devicetree/bindings/sound/apple,mca.yaml | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/sound/microchip,sama7g5-pdmc.yaml | 6 | ||||
-rw-r--r-- | include/sound/soc-component.h | 2 | ||||
-rw-r--r-- | sound/soc/amd/yc/acp6x-mach.c | 14 | ||||
-rw-r--r-- | sound/soc/apple/mca.c | 31 | ||||
-rw-r--r-- | sound/soc/atmel/mchp-pdmc.c | 53 | ||||
-rw-r--r-- | sound/soc/atmel/sam9g20_wm8731.c | 3 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/codecs/adau7118.c | 19 | ||||
-rw-r--r-- | sound/soc/codecs/da7219-aad.c | 41 | ||||
-rw-r--r-- | sound/soc/codecs/da7219-aad.h | 4 | ||||
-rw-r--r-- | sound/soc/codecs/mt6358.c | 11 | ||||
-rw-r--r-- | sound/soc/codecs/sma1303.c | 2 | ||||
-rw-r--r-- | sound/soc/intel/boards/sof_rt5682.c | 23 | ||||
-rw-r--r-- | sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 12 | ||||
-rw-r--r-- | sound/soc/mediatek/mt8183/mt8183-dai-i2s.c | 21 | ||||
-rw-r--r-- | sound/soc/mediatek/mt8188/mt8188-dai-etdm.c | 11 | ||||
-rw-r--r-- | sound/soc/mediatek/mt8192/mt8192-dai-adda.c | 58 | ||||
-rw-r--r-- | sound/soc/mediatek/mt8195/mt8195-dai-etdm.c | 3 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 64 | ||||
-rw-r--r-- | sound/soc/soc-pcm.c | 27 |
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, ®_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; |