Merge tag 'sound-6.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Sep 2022 11:36:10 +0000 (07:36 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Sep 2022 11:36:10 +0000 (07:36 -0400)
Pull sound fixes from Takashi Iwai:
 "Lots of small fixes for various drivers at this time, hopefully it
  will be the last big bump before 6.0 release.

  The significant changes are regression fixes for (yet again) HD-audio
  memory allocations and USB-audio PCM parameter handling, while there
  are many small ASoC device-specific fixes as well as a few
  out-of-bounds and race issues spotted by fuzzers"

* tag 'sound-6.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (29 commits)
  ALSA: usb-audio: Clear fixed clock rate at closing EP
  ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
  ALSA: hda: Once again fix regression of page allocations with IOMMU
  ALSA: usb-audio: Fix an out-of-bounds bug in __snd_usb_parse_audio_interface()
  ALSA: hda/tegra: Align BDL entry to 4KB boundary
  ALSA: hda/sigmatel: Fix unused variable warning for beep power change
  ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
  ALSA: hda/sigmatel: Keep power up while beep is enabled
  ALSA: aloop: Fix random zeros in capture data when using jiffies timer
  ALSA: usb-audio: Split endpoint setups for hw_params and prepare
  ALSA: usb-audio: Register card again for iface over delayed_register option
  ALSA: usb-audio: Inform the delayed registration more properly
  ASoC: fsl_aud2htx: Add error handler for pm_runtime_enable
  ASoC: fsl_aud2htx: register platform component before registering cpu dai
  ASoC: SOF: ipc4-topology: fix alh_group_ida max value
  ASoC: mchp-spdiftx: Fix clang -Wbitfield-constant-conversion
  ASoC: SOF: Kconfig: Make IPC_MESSAGE_INJECTOR depend on SND_SOC_SOF
  ASoC: SOF: Kconfig: Make IPC_FLOOD_TEST depend on SND_SOC_SOF
  ASoC: fsl_mqs: Fix supported clock DAI format
  ASoC: nau8540: Implement hw constraint for rates
  ...

26 files changed:
sound/core/memalloc.c
sound/core/oss/pcm_oss.c
sound/drivers/aloop.c
sound/pci/emu10k1/emupcm.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_sigmatel.c
sound/soc/atmel/mchp-spdiftx.c
sound/soc/codecs/cs42l42.c
sound/soc/codecs/nau8540.c
sound/soc/codecs/nau8821.c
sound/soc/codecs/nau8824.c
sound/soc/codecs/nau8825.c
sound/soc/fsl/fsl_aud2htx.c
sound/soc/fsl/fsl_mqs.c
sound/soc/fsl/fsl_sai.c
sound/soc/mediatek/mt8186/mt8186-dai-adda.c
sound/soc/qcom/sm8250.c
sound/soc/sof/Kconfig
sound/soc/sof/ipc4-topology.c
sound/usb/card.c
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/pcm.c
sound/usb/quirks.c
sound/usb/stream.c

index b665ac6..cfcd8ef 100644 (file)
@@ -543,10 +543,13 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
        dmab->dev.need_sync = dma_need_sync(dmab->dev.dev,
                                            sg_dma_address(sgt->sgl));
        p = dma_vmap_noncontiguous(dmab->dev.dev, size, sgt);
-       if (p)
+       if (p) {
                dmab->private_data = sgt;
-       else
+               /* store the first page address for convenience */
+               dmab->addr = snd_sgbuf_get_addr(dmab, 0);
+       } else {
                dma_free_noncontiguous(dmab->dev.dev, size, sgt, dmab->dev.dir);
+       }
        return p;
 }
 
@@ -780,6 +783,8 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
        if (!p)
                goto error;
        dmab->private_data = sgbuf;
+       /* store the first page address for convenience */
+       dmab->addr = snd_sgbuf_get_addr(dmab, 0);
        return p;
 
  error:
index 90c3a36..02df915 100644 (file)
@@ -1672,14 +1672,14 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
                runtime = substream->runtime;
                if (atomic_read(&substream->mmap_count))
                        goto __direct;
-               err = snd_pcm_oss_make_ready(substream);
-               if (err < 0)
-                       return err;
                atomic_inc(&runtime->oss.rw_ref);
                if (mutex_lock_interruptible(&runtime->oss.params_lock)) {
                        atomic_dec(&runtime->oss.rw_ref);
                        return -ERESTARTSYS;
                }
+               err = snd_pcm_oss_make_ready_locked(substream);
+               if (err < 0)
+                       goto unlock;
                format = snd_pcm_oss_format_from(runtime->oss.format);
                width = snd_pcm_format_physical_width(format);
                if (runtime->oss.buffer_used > 0) {
index 9b4a7cd..12f12a2 100644 (file)
@@ -605,17 +605,18 @@ static unsigned int loopback_jiffies_timer_pos_update
                        cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
        struct loopback_pcm *dpcm_capt =
                        cable->streams[SNDRV_PCM_STREAM_CAPTURE];
-       unsigned long delta_play = 0, delta_capt = 0;
+       unsigned long delta_play = 0, delta_capt = 0, cur_jiffies;
        unsigned int running, count1, count2;
 
+       cur_jiffies = jiffies;
        running = cable->running ^ cable->pause;
        if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
-               delta_play = jiffies - dpcm_play->last_jiffies;
+               delta_play = cur_jiffies - dpcm_play->last_jiffies;
                dpcm_play->last_jiffies += delta_play;
        }
 
        if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
-               delta_capt = jiffies - dpcm_capt->last_jiffies;
+               delta_capt = cur_jiffies - dpcm_capt->last_jiffies;
                dpcm_capt->last_jiffies += delta_capt;
        }
 
index b2701a4..48af77a 100644 (file)
@@ -124,7 +124,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
        epcm->voices[0]->epcm = epcm;
        if (voices > 1) {
                for (i = 1; i < voices; i++) {
-                       epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i];
+                       epcm->voices[i] = &epcm->emu->voices[(epcm->voices[0]->number + i) % NUM_G];
                        epcm->voices[i]->epcm = epcm;
                }
        }
index a77165b..b20694f 100644 (file)
@@ -1817,7 +1817,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 
        /* use the non-cached pages in non-snoop mode */
        if (!azx_snoop(chip))
-               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC;
+               azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_WC_SG;
 
        if (chip->driver_type == AZX_DRIVER_NVIDIA) {
                dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
index 7debb2c..976a112 100644 (file)
@@ -474,7 +474,8 @@ MODULE_DEVICE_TABLE(of, hda_tegra_match);
 static int hda_tegra_probe(struct platform_device *pdev)
 {
        const unsigned int driver_flags = AZX_DCAPS_CORBRP_SELF_CLEAR |
-                                         AZX_DCAPS_PM_RUNTIME;
+                                         AZX_DCAPS_PM_RUNTIME |
+                                         AZX_DCAPS_4K_BDLE_BOUNDARY;
        struct snd_card *card;
        struct azx *chip;
        struct hda_tegra *hda;
index 61df4d3..7f340f1 100644 (file)
@@ -209,6 +209,7 @@ struct sigmatel_spec {
 
        /* beep widgets */
        hda_nid_t anabeep_nid;
+       bool beep_power_on;
 
        /* SPDIF-out mux */
        const char * const *spdif_labels;
@@ -4443,6 +4444,28 @@ static int stac_suspend(struct hda_codec *codec)
 
        return 0;
 }
+
+static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid)
+{
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+       struct sigmatel_spec *spec = codec->spec;
+#endif
+       int ret = snd_hda_gen_check_power_status(codec, nid);
+
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+       if (nid == spec->gen.beep_nid && codec->beep) {
+               if (codec->beep->enabled != spec->beep_power_on) {
+                       spec->beep_power_on = codec->beep->enabled;
+                       if (spec->beep_power_on)
+                               snd_hda_power_up_pm(codec);
+                       else
+                               snd_hda_power_down_pm(codec);
+               }
+               ret |= spec->beep_power_on;
+       }
+#endif
+       return ret;
+}
 #else
 #define stac_suspend           NULL
 #endif /* CONFIG_PM */
@@ -4455,6 +4478,7 @@ static const struct hda_codec_ops stac_patch_ops = {
        .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .suspend = stac_suspend,
+       .check_power_status = stac_check_power_status,
 #endif
 };
 
index 4850a17..ab2d7a7 100644 (file)
@@ -196,7 +196,7 @@ struct mchp_spdiftx_dev {
        struct clk                              *pclk;
        struct clk                              *gclk;
        unsigned int                            fmt;
-       int                                     gclk_enabled:1;
+       unsigned int                            gclk_enabled:1;
 };
 
 static inline int mchp_spdiftx_is_running(struct mchp_spdiftx_dev *dev)
index d545a59..daafd42 100644 (file)
@@ -1617,7 +1617,6 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
        unsigned int current_plug_status;
        unsigned int current_button_status;
        unsigned int i;
-       int report = 0;
 
        mutex_lock(&cs42l42->irq_lock);
        if (cs42l42->suspended) {
@@ -1711,13 +1710,15 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 
                        if (current_button_status & CS42L42_M_DETECT_TF_MASK) {
                                dev_dbg(cs42l42->dev, "Button released\n");
-                               report = 0;
+                               snd_soc_jack_report(cs42l42->jack, 0,
+                                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                                                   SND_JACK_BTN_2 | SND_JACK_BTN_3);
                        } else if (current_button_status & CS42L42_M_DETECT_FT_MASK) {
-                               report = cs42l42_handle_button_press(cs42l42);
-
+                               snd_soc_jack_report(cs42l42->jack,
+                                                   cs42l42_handle_button_press(cs42l42),
+                                                   SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+                                                   SND_JACK_BTN_2 | SND_JACK_BTN_3);
                        }
-                       snd_soc_jack_report(cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 |
-                                                                  SND_JACK_BTN_2 | SND_JACK_BTN_3);
                }
        }
 
index 58f70a0..0626d56 100644 (file)
@@ -357,17 +357,32 @@ static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
        {"AIFTX", NULL, "Digital CH4 Mux"},
 };
 
-static int nau8540_clock_check(struct nau8540 *nau8540, int rate, int osr)
+static const struct nau8540_osr_attr *
+nau8540_get_osr(struct nau8540 *nau8540)
 {
+       unsigned int osr;
+
+       regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
+       osr &= NAU8540_ADC_OSR_MASK;
        if (osr >= ARRAY_SIZE(osr_adc_sel))
-               return -EINVAL;
+               return NULL;
+       return &osr_adc_sel[osr];
+}
+
+static int nau8540_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
+       const struct nau8540_osr_attr *osr;
 
-       if (rate * osr > CLK_ADC_MAX) {
-               dev_err(nau8540->dev, "exceed the maximum frequency of CLK_ADC\n");
+       osr = nau8540_get_osr(nau8540);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_ADC_MAX / osr->osr);
 }
 
 static int nau8540_hw_params(struct snd_pcm_substream *substream,
@@ -375,7 +390,8 @@ static int nau8540_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8540 *nau8540 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr;
+       unsigned int val_len = 0;
+       const struct nau8540_osr_attr *osr;
 
        /* CLK_ADC = OSR * FS
         * ADC clock frequency is defined as Over Sampling Rate (OSR)
@@ -383,13 +399,14 @@ static int nau8540_hw_params(struct snd_pcm_substream *substream,
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       regmap_read(nau8540->regmap, NAU8540_REG_ADC_SAMPLE_RATE, &osr);
-       osr &= NAU8540_ADC_OSR_MASK;
-       if (nau8540_clock_check(nau8540, params_rate(params), osr))
+       osr = nau8540_get_osr(nau8540);
+       if (!osr || !osr->osr)
+               return -EINVAL;
+       if (params_rate(params) * osr->osr > CLK_ADC_MAX)
                return -EINVAL;
        regmap_update_bits(nau8540->regmap, NAU8540_REG_CLOCK_SRC,
                NAU8540_CLK_ADC_SRC_MASK,
-               osr_adc_sel[osr].clk_src << NAU8540_CLK_ADC_SRC_SFT);
+               osr->clk_src << NAU8540_CLK_ADC_SRC_SFT);
 
        switch (params_width(params)) {
        case 16:
@@ -515,6 +532,7 @@ static int nau8540_set_tdm_slot(struct snd_soc_dai *dai,
 
 
 static const struct snd_soc_dai_ops nau8540_dai_ops = {
+       .startup = nau8540_dai_startup,
        .hw_params = nau8540_hw_params,
        .set_fmt = nau8540_set_fmt,
        .set_tdm_slot = nau8540_set_tdm_slot,
index 2d21339..4a72b94 100644 (file)
@@ -670,28 +670,40 @@ static const struct snd_soc_dapm_route nau8821_dapm_routes[] = {
        {"HPOR", NULL, "Class G"},
 };
 
-static int nau8821_clock_check(struct nau8821 *nau8821,
-       int stream, int rate, int osr)
+static const struct nau8821_osr_attr *
+nau8821_get_osr(struct nau8821 *nau8821, int stream)
 {
-       int osrate = 0;
+       unsigned int osr;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               regmap_read(nau8821->regmap, NAU8821_R2C_DAC_CTRL1, &osr);
+               osr &= NAU8821_DAC_OVERSAMPLE_MASK;
                if (osr >= ARRAY_SIZE(osr_dac_sel))
-                       return -EINVAL;
-               osrate = osr_dac_sel[osr].osr;
+                       return NULL;
+               return &osr_dac_sel[osr];
        } else {
+               regmap_read(nau8821->regmap, NAU8821_R2B_ADC_RATE, &osr);
+               osr &= NAU8821_ADC_SYNC_DOWN_MASK;
                if (osr >= ARRAY_SIZE(osr_adc_sel))
-                       return -EINVAL;
-               osrate = osr_adc_sel[osr].osr;
+                       return NULL;
+               return &osr_adc_sel[osr];
        }
+}
 
-       if (!osrate || rate * osrate > CLK_DA_AD_MAX) {
-               dev_err(nau8821->dev,
-                       "exceed the maximum frequency of CLK_ADC or CLK_DAC");
+static int nau8821_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
+       const struct nau8821_osr_attr *osr;
+
+       osr = nau8821_get_osr(nau8821, substream->stream);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_DA_AD_MAX / osr->osr);
 }
 
 static int nau8821_hw_params(struct snd_pcm_substream *substream,
@@ -699,7 +711,8 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8821 *nau8821 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr, ctrl_val, bclk_fs, clk_div;
+       unsigned int val_len = 0, ctrl_val, bclk_fs, clk_div;
+       const struct nau8821_osr_attr *osr;
 
        nau8821->fs = params_rate(params);
        /* CLK_DAC or CLK_ADC = OSR * FS
@@ -708,27 +721,19 @@ static int nau8821_hw_params(struct snd_pcm_substream *substream,
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regmap_read(nau8821->regmap, NAU8821_R2C_DAC_CTRL1, &osr);
-               osr &= NAU8821_DAC_OVERSAMPLE_MASK;
-               if (nau8821_clock_check(nau8821, substream->stream,
-                       nau8821->fs, osr)) {
-                       return -EINVAL;
-               }
+       osr = nau8821_get_osr(nau8821, substream->stream);
+       if (!osr || !osr->osr)
+               return -EINVAL;
+       if (nau8821->fs * osr->osr > CLK_DA_AD_MAX)
+               return -EINVAL;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                regmap_update_bits(nau8821->regmap, NAU8821_R03_CLK_DIVIDER,
                        NAU8821_CLK_DAC_SRC_MASK,
-                       osr_dac_sel[osr].clk_src << NAU8821_CLK_DAC_SRC_SFT);
-       } else {
-               regmap_read(nau8821->regmap, NAU8821_R2B_ADC_RATE, &osr);
-               osr &= NAU8821_ADC_SYNC_DOWN_MASK;
-               if (nau8821_clock_check(nau8821, substream->stream,
-                       nau8821->fs, osr)) {
-                       return -EINVAL;
-               }
+                       osr->clk_src << NAU8821_CLK_DAC_SRC_SFT);
+       else
                regmap_update_bits(nau8821->regmap, NAU8821_R03_CLK_DIVIDER,
                        NAU8821_CLK_ADC_SRC_MASK,
-                       osr_adc_sel[osr].clk_src << NAU8821_CLK_ADC_SRC_SFT);
-       }
+                       osr->clk_src << NAU8821_CLK_ADC_SRC_SFT);
 
        /* make BCLK and LRC divde configuration if the codec as master. */
        regmap_read(nau8821->regmap, NAU8821_R1D_I2S_PCM_CTRL2, &ctrl_val);
@@ -843,6 +848,7 @@ static int nau8821_digital_mute(struct snd_soc_dai *dai, int mute,
 }
 
 static const struct snd_soc_dai_ops nau8821_dai_ops = {
+       .startup = nau8821_dai_startup,
        .hw_params = nau8821_hw_params,
        .set_fmt = nau8821_set_dai_fmt,
        .mute_stream = nau8821_digital_mute,
index ad54d70..1559645 100644 (file)
@@ -1014,27 +1014,42 @@ static irqreturn_t nau8824_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int nau8824_clock_check(struct nau8824 *nau8824,
-       int stream, int rate, int osr)
+static const struct nau8824_osr_attr *
+nau8824_get_osr(struct nau8824 *nau8824, int stream)
 {
-       int osrate;
+       unsigned int osr;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               regmap_read(nau8824->regmap,
+                           NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
+               osr &= NAU8824_DAC_OVERSAMPLE_MASK;
                if (osr >= ARRAY_SIZE(osr_dac_sel))
-                       return -EINVAL;
-               osrate = osr_dac_sel[osr].osr;
+                       return NULL;
+               return &osr_dac_sel[osr];
        } else {
+               regmap_read(nau8824->regmap,
+                           NAU8824_REG_ADC_FILTER_CTRL, &osr);
+               osr &= NAU8824_ADC_SYNC_DOWN_MASK;
                if (osr >= ARRAY_SIZE(osr_adc_sel))
-                       return -EINVAL;
-               osrate = osr_adc_sel[osr].osr;
+                       return NULL;
+               return &osr_adc_sel[osr];
        }
+}
+
+static int nau8824_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
+       const struct nau8824_osr_attr *osr;
 
-       if (!osrate || rate * osr > CLK_DA_AD_MAX) {
-               dev_err(nau8824->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
+       osr = nau8824_get_osr(nau8824, substream->stream);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_DA_AD_MAX / osr->osr);
 }
 
 static int nau8824_hw_params(struct snd_pcm_substream *substream,
@@ -1042,7 +1057,9 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
+       unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
+       const struct nau8824_osr_attr *osr;
+       int err = -EINVAL;
 
        nau8824_sema_acquire(nau8824, HZ);
 
@@ -1053,27 +1070,19 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
         * than 6.144 MHz.
         */
        nau8824->fs = params_rate(params);
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regmap_read(nau8824->regmap,
-                       NAU8824_REG_DAC_FILTER_CTRL_1, &osr);
-               osr &= NAU8824_DAC_OVERSAMPLE_MASK;
-               if (nau8824_clock_check(nau8824, substream->stream,
-                       nau8824->fs, osr))
-                       return -EINVAL;
+       osr = nau8824_get_osr(nau8824, substream->stream);
+       if (!osr || !osr->osr)
+               goto error;
+       if (nau8824->fs * osr->osr > CLK_DA_AD_MAX)
+               goto error;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
                        NAU8824_CLK_DAC_SRC_MASK,
-                       osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT);
-       } else {
-               regmap_read(nau8824->regmap,
-                       NAU8824_REG_ADC_FILTER_CTRL, &osr);
-               osr &= NAU8824_ADC_SYNC_DOWN_MASK;
-               if (nau8824_clock_check(nau8824, substream->stream,
-                       nau8824->fs, osr))
-                       return -EINVAL;
+                       osr->clk_src << NAU8824_CLK_DAC_SRC_SFT);
+       else
                regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
                        NAU8824_CLK_ADC_SRC_MASK,
-                       osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT);
-       }
+                       osr->clk_src << NAU8824_CLK_ADC_SRC_SFT);
 
        /* make BCLK and LRC divde configuration if the codec as master. */
        regmap_read(nau8824->regmap,
@@ -1090,7 +1099,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                else if (bclk_fs <= 256)
                        bclk_div = 0;
                else
-                       return -EINVAL;
+                       goto error;
                regmap_update_bits(nau8824->regmap,
                        NAU8824_REG_PORT0_I2S_PCM_CTRL_2,
                        NAU8824_I2S_LRC_DIV_MASK | NAU8824_I2S_BLK_DIV_MASK,
@@ -1111,15 +1120,17 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                val_len |= NAU8824_I2S_DL_32;
                break;
        default:
-               return -EINVAL;
+               goto error;
        }
 
        regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
                NAU8824_I2S_DL_MASK, val_len);
+       err = 0;
 
+ error:
        nau8824_sema_release(nau8824);
 
-       return 0;
+       return err;
 }
 
 static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -1128,8 +1139,6 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
        unsigned int ctrl1_val = 0, ctrl2_val = 0;
 
-       nau8824_sema_acquire(nau8824, HZ);
-
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                ctrl2_val |= NAU8824_I2S_MS_MASTER;
@@ -1171,6 +1180,8 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
+       nau8824_sema_acquire(nau8824, HZ);
+
        regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
                NAU8824_I2S_DF_MASK | NAU8824_I2S_BP_MASK |
                NAU8824_I2S_PCMB_EN, ctrl1_val);
@@ -1547,6 +1558,7 @@ static const struct snd_soc_component_driver nau8824_component_driver = {
 };
 
 static const struct snd_soc_dai_ops nau8824_dai_ops = {
+       .startup = nau8824_dai_startup,
        .hw_params = nau8824_hw_params,
        .set_fmt = nau8824_set_fmt,
        .set_tdm_slot = nau8824_set_tdm_slot,
index 54ef7b0..8213273 100644 (file)
@@ -1247,27 +1247,42 @@ static const struct snd_soc_dapm_route nau8825_dapm_routes[] = {
        {"HPOR", NULL, "Class G"},
 };
 
-static int nau8825_clock_check(struct nau8825 *nau8825,
-       int stream, int rate, int osr)
+static const struct nau8825_osr_attr *
+nau8825_get_osr(struct nau8825 *nau8825, int stream)
 {
-       int osrate;
+       unsigned int osr;
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               regmap_read(nau8825->regmap,
+                           NAU8825_REG_DAC_CTRL1, &osr);
+               osr &= NAU8825_DAC_OVERSAMPLE_MASK;
                if (osr >= ARRAY_SIZE(osr_dac_sel))
-                       return -EINVAL;
-               osrate = osr_dac_sel[osr].osr;
+                       return NULL;
+               return &osr_dac_sel[osr];
        } else {
+               regmap_read(nau8825->regmap,
+                           NAU8825_REG_ADC_RATE, &osr);
+               osr &= NAU8825_ADC_SYNC_DOWN_MASK;
                if (osr >= ARRAY_SIZE(osr_adc_sel))
-                       return -EINVAL;
-               osrate = osr_adc_sel[osr].osr;
+                       return NULL;
+               return &osr_adc_sel[osr];
        }
+}
 
-       if (!osrate || rate * osr > CLK_DA_AD_MAX) {
-               dev_err(nau8825->dev, "exceed the maximum frequency of CLK_ADC or CLK_DAC\n");
+static int nau8825_dai_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
+       const struct nau8825_osr_attr *osr;
+
+       osr = nau8825_get_osr(nau8825, substream->stream);
+       if (!osr || !osr->osr)
                return -EINVAL;
-       }
 
-       return 0;
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           0, CLK_DA_AD_MAX / osr->osr);
 }
 
 static int nau8825_hw_params(struct snd_pcm_substream *substream,
@@ -1276,7 +1291,9 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_component *component = dai->component;
        struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
-       unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
+       unsigned int val_len = 0, ctrl_val, bclk_fs, bclk_div;
+       const struct nau8825_osr_attr *osr;
+       int err = -EINVAL;
 
        nau8825_sema_acquire(nau8825, 3 * HZ);
 
@@ -1286,29 +1303,19 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
         * values must be selected such that the maximum frequency is less
         * than 6.144 MHz.
         */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
-               osr &= NAU8825_DAC_OVERSAMPLE_MASK;
-               if (nau8825_clock_check(nau8825, substream->stream,
-                       params_rate(params), osr)) {
-                       nau8825_sema_release(nau8825);
-                       return -EINVAL;
-               }
+       osr = nau8825_get_osr(nau8825, substream->stream);
+       if (!osr || !osr->osr)
+               goto error;
+       if (params_rate(params) * osr->osr > CLK_DA_AD_MAX)
+               goto error;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
                        NAU8825_CLK_DAC_SRC_MASK,
-                       osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
-       } else {
-               regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
-               osr &= NAU8825_ADC_SYNC_DOWN_MASK;
-               if (nau8825_clock_check(nau8825, substream->stream,
-                       params_rate(params), osr)) {
-                       nau8825_sema_release(nau8825);
-                       return -EINVAL;
-               }
+                       osr->clk_src << NAU8825_CLK_DAC_SRC_SFT);
+       else
                regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
                        NAU8825_CLK_ADC_SRC_MASK,
-                       osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
-       }
+                       osr->clk_src << NAU8825_CLK_ADC_SRC_SFT);
 
        /* make BCLK and LRC divde configuration if the codec as master. */
        regmap_read(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, &ctrl_val);
@@ -1321,10 +1328,8 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
                        bclk_div = 1;
                else if (bclk_fs <= 128)
                        bclk_div = 0;
-               else {
-                       nau8825_sema_release(nau8825);
-                       return -EINVAL;
-               }
+               else
+                       goto error;
                regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
                        NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK,
                        ((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div);
@@ -1344,17 +1349,18 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
                val_len |= NAU8825_I2S_DL_32;
                break;
        default:
-               nau8825_sema_release(nau8825);
-               return -EINVAL;
+               goto error;
        }
 
        regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
                NAU8825_I2S_DL_MASK, val_len);
+       err = 0;
 
+ error:
        /* Release the semaphore. */
        nau8825_sema_release(nau8825);
 
-       return 0;
+       return err;
 }
 
 static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
@@ -1420,6 +1426,7 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 }
 
 static const struct snd_soc_dai_ops nau8825_dai_ops = {
+       .startup        = nau8825_dai_startup,
        .hw_params      = nau8825_hw_params,
        .set_fmt        = nau8825_set_dai_fmt,
 };
index 873295f..1e421d9 100644 (file)
@@ -234,18 +234,26 @@ static int fsl_aud2htx_probe(struct platform_device *pdev)
 
        regcache_cache_only(aud2htx->regmap, true);
 
+       /*
+        * Register platform component before registering cpu dai for there
+        * is not defer probe for platform component in snd_soc_add_pcm_runtime().
+        */
+       ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to pcm register\n");
+               pm_runtime_disable(&pdev->dev);
+               return ret;
+       }
+
        ret = devm_snd_soc_register_component(&pdev->dev,
                                              &fsl_aud2htx_component,
                                              &fsl_aud2htx_dai, 1);
        if (ret) {
                dev_err(&pdev->dev, "failed to register ASoC DAI\n");
+               pm_runtime_disable(&pdev->dev);
                return ret;
        }
 
-       ret = imx_pcm_dma_init(pdev);
-       if (ret)
-               dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret);
-
        return ret;
 }
 
index c1e2f67..4922e67 100644 (file)
@@ -122,7 +122,7 @@ static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        }
 
        switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
-       case SND_SOC_DAIFMT_BP_FP:
+       case SND_SOC_DAIFMT_CBC_CFC:
                break;
        default:
                return -EINVAL;
index 7523bb9..d430eec 100644 (file)
@@ -1306,7 +1306,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
                sai->mclk_clk[i] = devm_clk_get(dev, tmp);
                if (IS_ERR(sai->mclk_clk[i])) {
                        dev_err(dev, "failed to get mclk%d clock: %ld\n",
-                                       i + 1, PTR_ERR(sai->mclk_clk[i]));
+                                       i, PTR_ERR(sai->mclk_clk[i]));
                        sai->mclk_clk[i] = NULL;
                }
        }
index 2667045..0944024 100644 (file)
@@ -271,9 +271,6 @@ static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w,
                /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
                usleep_range(125, 135);
                mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 1);
-
-               /* reset dmic */
-               afe_priv->mtkaif_dmic = 0;
                break;
        default:
                break;
index ce4a571..98a2fde 100644 (file)
@@ -270,6 +270,7 @@ static int sm8250_platform_probe(struct platform_device *pdev)
        if (!card)
                return -ENOMEM;
 
+       card->owner = THIS_MODULE;
        /* Allocate the private data */
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
index e90f173..37f7df5 100644 (file)
@@ -196,6 +196,7 @@ config SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE
 
 config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST
        tristate "SOF enable IPC flood test"
+       depends on SND_SOC_SOF
        select SND_SOC_SOF_CLIENT
        help
          This option enables a separate client device for IPC flood test
@@ -214,6 +215,7 @@ config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM
 
 config SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR
        tristate "SOF enable IPC message injector"
+       depends on SND_SOC_SOF
        select SND_SOC_SOF_CLIENT
        help
          This option enables the IPC message injector which can be used to send
index af072b4..64929dc 100644 (file)
@@ -771,7 +771,7 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
                goto err;
 
        ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
-                                   swidget->num_tuples, sizeof(src), 1);
+                                   swidget->num_tuples, sizeof(*src), 1);
        if (ret) {
                dev_err(scomp->dev, "Parsing SRC tokens failed\n");
                goto err;
@@ -1251,7 +1251,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
                        if (blob->alh_cfg.count > 1) {
                                int group_id;
 
-                               group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT,
+                               group_id = ida_alloc_max(&alh_group_ida, ALH_MULTI_GTW_COUNT - 1,
                                                         GFP_KERNEL);
 
                                if (group_id < 0)
index d356743..706d249 100644 (file)
@@ -699,7 +699,7 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
                if (delayed_register[i] &&
                    sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
                    id == chip->usb_id)
-                       return inum != iface;
+                       return iface < inum;
        }
 
        return false;
index 0d7b73b..8c8f9a8 100644 (file)
@@ -758,7 +758,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
  * The endpoint needs to be closed via snd_usb_endpoint_close() later.
  *
  * Note that this function doesn't configure the endpoint.  The substream
- * needs to set it up later via snd_usb_endpoint_configure().
+ * needs to set it up later via snd_usb_endpoint_set_params() and
+ * snd_usb_endpoint_prepare().
  */
 struct snd_usb_endpoint *
 snd_usb_endpoint_open(struct snd_usb_audio *chip,
@@ -924,6 +925,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
                endpoint_set_interface(chip, ep, false);
 
        if (!--ep->opened) {
+               if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
+                       ep->clock_ref->rate = 0;
                ep->iface = 0;
                ep->altsetting = 0;
                ep->cur_audiofmt = NULL;
@@ -1290,12 +1293,13 @@ out_of_memory:
 /*
  * snd_usb_endpoint_set_params: configure an snd_usb_endpoint
  *
+ * It's called either from hw_params callback.
  * Determine the number of URBs to be used on this endpoint.
  * An endpoint must be configured before it can be started.
  * An endpoint that is already running can not be reconfigured.
  */
-static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
-                                      struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+                               struct snd_usb_endpoint *ep)
 {
        const struct audioformat *fmt = ep->cur_audiofmt;
        int err;
@@ -1378,18 +1382,18 @@ static int init_sample_rate(struct snd_usb_audio *chip,
 }
 
 /*
- * snd_usb_endpoint_configure: Configure the endpoint
+ * snd_usb_endpoint_prepare: Prepare the endpoint
  *
  * This function sets up the EP to be fully usable state.
- * It's called either from hw_params or prepare callback.
+ * It's called either from prepare callback.
  * The function checks need_setup flag, and performs nothing unless needed,
  * so it's safe to call this multiple times.
  *
  * This returns zero if unchanged, 1 if the configuration has changed,
  * or a negative error code.
  */
-int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
-                              struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
+                            struct snd_usb_endpoint *ep)
 {
        bool iface_first;
        int err = 0;
@@ -1410,9 +1414,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
                        if (err < 0)
                                goto unlock;
                }
-               err = snd_usb_endpoint_set_params(chip, ep);
-               if (err < 0)
-                       goto unlock;
                goto done;
        }
 
@@ -1440,10 +1441,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
        if (err < 0)
                goto unlock;
 
-       err = snd_usb_endpoint_set_params(chip, ep);
-       if (err < 0)
-               goto unlock;
-
        err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
        if (err < 0)
                goto unlock;
index 6a9af04..e67ea28 100644 (file)
@@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
                      bool is_sync_ep);
 void snd_usb_endpoint_close(struct snd_usb_audio *chip,
                            struct snd_usb_endpoint *ep);
-int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
-                              struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+                               struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
+                            struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
 
 bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
index d45d1d7..b604f7e 100644 (file)
@@ -443,17 +443,17 @@ static int configure_endpoints(struct snd_usb_audio *chip,
                if (stop_endpoints(subs, false))
                        sync_pending_stops(subs);
                if (subs->sync_endpoint) {
-                       err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
+                       err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
                        if (err < 0)
                                return err;
                }
-               err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
+               err = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
                if (err < 0)
                        return err;
                snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
        } else {
                if (subs->sync_endpoint) {
-                       err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
+                       err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
                        if (err < 0)
                                return err;
                }
@@ -551,7 +551,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
        subs->cur_audiofmt = fmt;
        mutex_unlock(&chip->mutex);
 
-       ret = configure_endpoints(chip, subs);
+       if (subs->sync_endpoint) {
+               ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
+               if (ret < 0)
+                       goto unlock;
+       }
+
+       ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
 
  unlock:
        if (ret < 0)
index 9bfead5..5b4d8f5 100644 (file)
@@ -1764,7 +1764,7 @@ bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
 
        for (q = registration_quirks; q->usb_id; q++)
                if (chip->usb_id == q->usb_id)
-                       return iface != q->interface;
+                       return iface < q->interface;
 
        /* Register as normal */
        return false;
index ceb93d7..f10f4e6 100644 (file)
@@ -495,6 +495,10 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                        return 0;
                }
        }
+
+       if (chip->card->registered)
+               chip->need_delayed_register = true;
+
        /* look for an empty stream */
        list_for_each_entry(as, &chip->pcm_list, list) {
                if (as->fmt_type != fp->fmt_type)
@@ -502,9 +506,6 @@ static int __snd_usb_add_audio_stream(struct snd_usb_audio *chip,
                subs = &as->substream[stream];
                if (subs->ep_num)
                        continue;
-               if (snd_device_get_state(chip->card, as->pcm) !=
-                   SNDRV_DEV_BUILD)
-                       chip->need_delayed_register = true;
                err = snd_pcm_new_stream(as->pcm, stream, 1);
                if (err < 0)
                        return err;
@@ -1105,7 +1106,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
         * Dallas DS4201 workaround: It presents 5 altsettings, but the last
         * one misses syncpipe, and does not produce any sound.
         */
-       if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+       if (chip->usb_id == USB_ID(0x04fa, 0x4201) && num >= 4)
                num = 4;
 
        for (i = 0; i < num; i++) {