Merge branch 'for-5.2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorMark Brown <broonie@kernel.org>
Tue, 21 May 2019 21:00:33 +0000 (22:00 +0100)
committerMark Brown <broonie@kernel.org>
Tue, 21 May 2019 21:00:33 +0000 (22:00 +0100)
1  2 
sound/soc/codecs/cs42xx8.c
sound/soc/codecs/rt5677-spi.c
sound/soc/fsl/fsl_asrc.c
sound/soc/generic/simple-card.c
sound/soc/intel/boards/sof_rt5682.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c

index 3e8dbf63adbe42484c9db2898197601a5decc7f6,28a4ac36c4f856b3ec3b9242fdf60a7fa0100cda..b377cddaf2e606074118af15b7b13a786925e05c
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/delay.h>
  #include <linux/module.h>
  #include <linux/of_device.h>
 +#include <linux/of_gpio.h>
  #include <linux/pm_runtime.h>
  #include <linux/regulator/consumer.h>
  #include <sound/pcm_params.h>
@@@ -46,7 -45,6 +46,7 @@@ struct cs42xx8_priv 
        bool slave_mode;
        unsigned long sysclk;
        u32 tx_channels;
 +      struct gpio_desc *gpiod_reset;
  };
  
  /* -127.5dB to 0dB with step of 0.5dB */
@@@ -469,13 -467,6 +469,13 @@@ int cs42xx8_probe(struct device *dev, s
                return -EINVAL;
        }
  
 +      cs42xx8->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
 +                                                      GPIOD_OUT_HIGH);
 +      if (IS_ERR(cs42xx8->gpiod_reset))
 +              return PTR_ERR(cs42xx8->gpiod_reset);
 +
 +      gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0);
 +
        cs42xx8->clk = devm_clk_get(dev, "mclk");
        if (IS_ERR(cs42xx8->clk)) {
                dev_err(dev, "failed to get the clock: %ld\n",
@@@ -556,8 -547,6 +556,8 @@@ static int cs42xx8_runtime_resume(struc
                return ret;
        }
  
 +      gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 0);
 +
        ret = regulator_bulk_enable(ARRAY_SIZE(cs42xx8->supplies),
                                    cs42xx8->supplies);
        if (ret) {
        msleep(5);
  
        regcache_cache_only(cs42xx8->regmap, false);
+       regcache_mark_dirty(cs42xx8->regmap);
  
        ret = regcache_sync(cs42xx8->regmap);
        if (ret) {
@@@ -596,8 -586,6 +597,8 @@@ static int cs42xx8_runtime_suspend(stru
        regulator_bulk_disable(ARRAY_SIZE(cs42xx8->supplies),
                               cs42xx8->supplies);
  
 +      gpiod_set_value_cansleep(cs42xx8->gpiod_reset, 1);
 +
        clk_disable_unprepare(cs42xx8->clk);
  
        return 0;
index 871ccb37318daeebc7a9b5e1a925e75595bc124c,a4dfa0345c6e9d4956e0883041af7708930da38a..770fa09609cf7755044e672a6f8ffc3fe9c3dc6c
@@@ -29,8 -29,6 +29,8 @@@
  
  #include "rt5677-spi.h"
  
 +#define DRV_NAME "rt5677spi"
 +
  #define RT5677_SPI_BURST_LEN  240
  #define RT5677_SPI_HEADER     5
  #define RT5677_SPI_FREQ               6000000
@@@ -103,7 -101,7 +103,7 @@@ static void rt5677_spi_reverse(u8 *dst
        u32 word_size = min_t(u32, dstlen, 8);
  
        for (w = 0; w < dstlen; w += word_size) {
-               for (i = 0; i < word_size; i++) {
+               for (i = 0; i < word_size && i + w < dstlen; i++) {
                        si = w + word_size - i - 1;
                        dst[w + i] = si < srclen ? src[si] : 0;
                }
@@@ -154,8 -152,9 +154,9 @@@ int rt5677_spi_read(u32 addr, void *rxb
                status |= spi_sync(g_spi, &m);
                mutex_unlock(&spi_mutex);
  
                /* Copy data back to caller buffer */
-               rt5677_spi_reverse(cb + offset, t[1].len, body, t[1].len);
+               rt5677_spi_reverse(cb + offset, len - offset, body, t[1].len);
        }
        return status;
  }
@@@ -234,7 -233,7 +235,7 @@@ MODULE_DEVICE_TABLE(acpi, rt5677_spi_ac
  
  static struct spi_driver rt5677_spi_driver = {
        .driver = {
 -              .name = "rt5677",
 +              .name = DRV_NAME,
                .acpi_match_table = ACPI_PTR(rt5677_spi_acpi_id),
        },
        .probe = rt5677_spi_probe,
diff --combined sound/soc/fsl/fsl_asrc.c
index 71793d3dc75ca58bf3ec7d96ee19bbd9b072b3d4,ea035c12a325ee1e47a0514e76dba92ed15be7f3..a8d6710f25416ca5a3d560638614e4344ae1b822
  #define pair_dbg(fmt, ...) \
        dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
  
 -/* Sample rates are aligned with that defined in pcm.h file */
 -static const u8 process_option[][12][2] = {
 -      /* 8kHz 11.025kHz 16kHz 22.05kHz 32kHz 44.1kHz 48kHz   64kHz   88.2kHz 96kHz   176kHz  192kHz */
 -      {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 5512Hz */
 -      {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 8kHz */
 -      {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 11025Hz */
 -      {{1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 16kHz */
 -      {{1, 2}, {1, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},},      /* 22050Hz */
 -      {{1, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},},      /* 32kHz */
 -      {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},      /* 44.1kHz */
 -      {{2, 2}, {2, 2}, {2, 1}, {2, 1}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},},      /* 48kHz */
 -      {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},},      /* 64kHz */
 -      {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},      /* 88.2kHz */
 -      {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},},      /* 96kHz */
 -      {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},      /* 176kHz */
 -      {{2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},},      /* 192kHz */
 -};
 -
  /* Corresponding to process_option */
  static int supported_input_rate[] = {
        5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200,
@@@ -61,52 -79,6 +61,52 @@@ static unsigned char output_clk_map_imx
  
  static unsigned char *clk_map[2];
  
 +/**
 + * Select the pre-processing and post-processing options
 + * Make sure to exclude following unsupported cases before
 + * calling this function:
 + * 1) inrate > 8.125 * outrate
 + * 2) inrate > 16.125 * outrate
 + *
 + * inrate: input sample rate
 + * outrate: output sample rate
 + * pre_proc: return value for pre-processing option
 + * post_proc: return value for post-processing option
 + */
 +static void fsl_asrc_sel_proc(int inrate, int outrate,
 +                           int *pre_proc, int *post_proc)
 +{
 +      bool post_proc_cond2;
 +      bool post_proc_cond0;
 +
 +      /* select pre_proc between [0, 2] */
 +      if (inrate * 8 > 33 * outrate)
 +              *pre_proc = 2;
 +      else if (inrate * 8 > 15 * outrate) {
 +              if (inrate > 152000)
 +                      *pre_proc = 2;
 +              else
 +                      *pre_proc = 1;
 +      } else if (inrate < 76000)
 +              *pre_proc = 0;
 +      else if (inrate > 152000)
 +              *pre_proc = 2;
 +      else
 +              *pre_proc = 1;
 +
 +      /* Condition for selection of post-processing */
 +      post_proc_cond2 = (inrate * 15 > outrate * 16 && outrate < 56000) ||
 +                        (inrate > 56000 && outrate < 56000);
 +      post_proc_cond0 = inrate * 23 < outrate * 8;
 +
 +      if (post_proc_cond2)
 +              *post_proc = 2;
 +      else if (post_proc_cond0)
 +              *post_proc = 0;
 +      else
 +              *post_proc = 1;
 +}
 +
  /**
   * Request ASRC pair
   *
@@@ -267,7 -239,6 +267,7 @@@ static int fsl_asrc_config_pair(struct 
        u32 inrate, outrate, indiv, outdiv;
        u32 clk_index[2], div[2];
        int in, out, channels;
 +      int pre_proc, post_proc;
        struct clk *clk;
        bool ideal;
  
                return -EINVAL;
        }
  
-       if ((outrate > 8000 && outrate < 30000) &&
-           (outrate/inrate > 24 || inrate/outrate > 8)) {
+       if ((outrate >= 8000 && outrate <= 30000) &&
+           (outrate > 24 * inrate || inrate > 8 * outrate)) {
                pair_err("exceed supported ratio range [1/24, 8] for \
                                inrate/outrate: %d/%d\n", inrate, outrate);
                return -EINVAL;
                           ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index),
                           ASRCTR_IDR(index) | ASRCTR_USR(index));
  
 +      fsl_asrc_sel_proc(inrate, outrate, &pre_proc, &post_proc);
 +
        /* Apply configurations for pre- and post-processing */
        regmap_update_bits(asrc_priv->regmap, REG_ASRCFG,
                           ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index),
 -                         ASRCFG_PREMOD(index, process_option[in][out][0]) |
 -                         ASRCFG_POSTMOD(index, process_option[in][out][1]));
 +                         ASRCFG_PREMOD(index, pre_proc) |
 +                         ASRCFG_POSTMOD(index, post_proc));
  
        return fsl_asrc_set_ideal_ratio(pair, inrate, outrate);
  }
index d16e894fce2b182e7502b78f266a0e058708a9f4,c2c8dcbcf7951d6b9b1561f82cc4918b5758d8da..c2a2c5fd0801bc9c0d18b5b169dc46453368f6ed
@@@ -283,11 -283,6 +283,6 @@@ static int simple_dai_link_of(struct as
        codec_dai               =
        dai_props->codec_dai    = &priv->dais[li->dais++];
  
-       ret = asoc_simple_parse_daifmt(dev, node, codec,
-                                      prefix, &dai_link->dai_fmt);
-       if (ret < 0)
-               goto dai_link_of_err;
        simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
  
        ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
        if (ret < 0)
                goto dai_link_of_err;
  
+       ret = asoc_simple_parse_daifmt(dev, node, dai_link->codecs->of_node,
+                                      prefix, &dai_link->dai_fmt);
+       if (ret < 0)
+               goto dai_link_of_err;
        ret = asoc_simple_parse_platform(plat, dai_link);
        if (ret < 0)
                goto dai_link_of_err;
@@@ -607,7 -607,7 +607,7 @@@ static int simple_soc_probe(struct snd_
        return 0;
  }
  
 -static int simple_probe(struct platform_device *pdev)
 +static int asoc_simple_probe(struct platform_device *pdev)
  {
        struct asoc_simple_priv *priv;
        struct device *dev = &pdev->dev;
@@@ -705,7 -705,7 +705,7 @@@ err
        return ret;
  }
  
 -static int simple_remove(struct platform_device *pdev)
 +static int asoc_simple_remove(struct platform_device *pdev)
  {
        struct snd_soc_card *card = platform_get_drvdata(pdev);
  
@@@ -726,8 -726,8 +726,8 @@@ static struct platform_driver asoc_simp
                .pm = &snd_soc_pm_ops,
                .of_match_table = simple_of_match,
        },
 -      .probe = simple_probe,
 -      .remove = simple_remove,
 +      .probe = asoc_simple_probe,
 +      .remove = asoc_simple_remove,
  };
  
  module_platform_driver(asoc_simple_card);
index fea42e2753261705e53b85396a76ad3d20d0d037,3343dbcd506fdc8de46faaf17ec42f0f392dcf21..e441dc9799666ffb919bcfa09ea52e71ef13df8c
  #define SOF_RT5682_MCLK_EN                    BIT(3)
  #define SOF_RT5682_MCLK_24MHZ                 BIT(4)
  #define SOF_SPEAKER_AMP_PRESENT               BIT(5)
- #define SOF_RT5682_SSP_AMP(quirk)             ((quirk) & GENMASK(8, 6))
- #define SOF_RT5682_SSP_AMP_MASK                       (GENMASK(8, 6))
  #define SOF_RT5682_SSP_AMP_SHIFT              6
+ #define SOF_RT5682_SSP_AMP_MASK                 (GENMASK(8, 6))
+ #define SOF_RT5682_SSP_AMP(quirk)     \
+       (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK)
  
  /* Default: MCLK on, MCLK 19.2M, SSP0  */
  static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN |
@@@ -144,9 -145,9 +145,9 @@@ static int sof_rt5682_codec_init(struc
        jack = &ctx->sof_headset;
  
        snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
-       snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
-       snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
-       snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+       snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
        ret = snd_soc_component_set_jack(component, jack, NULL);
  
        if (ret) {
@@@ -519,7 -520,6 +520,7 @@@ static int sof_audio_probe(struct platf
  
        /* compute number of dai links */
        sof_audio_card_rt5682.num_links = 1 + dmic_num + hdmi_num;
 +
        if (sof_rt5682_quirk & SOF_SPEAKER_AMP_PRESENT)
                sof_audio_card_rt5682.num_links++;
  
diff --combined sound/soc/soc-dapm.c
index a4d6c068b5453386f7015a3ebdd791931b9a18dd,62e27defce56d8a5e466faa218bb81ab1a948313..b71ddaca70e516df1b84bd9d89b7356b969cc0de
@@@ -883,7 -883,6 +883,7 @@@ static int dapm_create_or_share_kcontro
                        case snd_soc_dapm_switch:
                        case snd_soc_dapm_mixer:
                        case snd_soc_dapm_pga:
 +                      case snd_soc_dapm_effect:
                        case snd_soc_dapm_out_drv:
                                wname_in_long_name = true;
                                kcname_in_long_name = true;
@@@ -2245,7 -2244,7 +2245,7 @@@ static int soc_dapm_mux_update_power(st
        dapm_kcontrol_for_each_path(path, kcontrol) {
                found = 1;
                /* we now need to match the string in the enum to the path */
 -              if (!(strcmp(path->name, e->texts[mux])))
 +              if (e && !(strcmp(path->name, e->texts[mux])))
                        connect = true;
                else
                        connect = false;
@@@ -2371,7 -2370,6 +2371,7 @@@ static ssize_t dapm_widget_show_compone
                case snd_soc_dapm_dac:
                case snd_soc_dapm_adc:
                case snd_soc_dapm_pga:
 +              case snd_soc_dapm_effect:
                case snd_soc_dapm_out_drv:
                case snd_soc_dapm_mixer:
                case snd_soc_dapm_mixer_named_ctl:
@@@ -3199,7 -3197,6 +3199,7 @@@ int snd_soc_dapm_new_widgets(struct snd
                        dapm_new_mux(w);
                        break;
                case snd_soc_dapm_pga:
 +              case snd_soc_dapm_effect:
                case snd_soc_dapm_out_drv:
                        dapm_new_pga(w);
                        break;
@@@ -3831,8 -3828,8 +3831,8 @@@ static int snd_soc_dai_link_event(struc
                                                ret);
                                        goto out;
                                }
-                               source->active++;
                        }
+                       source->active++;
                        ret = soc_dai_hw_params(&substream, params, source);
                        if (ret < 0)
                                goto out;
                                                ret);
                                        goto out;
                                }
-                               sink->active++;
                        }
+                       sink->active++;
                        ret = soc_dai_hw_params(&substream, params, sink);
                        if (ret < 0)
                                goto out;
diff --combined sound/soc/soc-pcm.c
index 4a7096a22b28836c818a70f3e5a79a49d8d853db,7347e6f9924810a9837032f8b07b49908d2c5ab2..4878d22ebd8c3dd02ea0efe9333bc1ee37ef5570
@@@ -43,8 -43,8 +43,8 @@@ static bool snd_soc_dai_stream_valid(st
        else
                codec_stream = &dai->driver->capture;
  
 -      /* If the codec specifies any rate at all, it supports the stream. */
 -      return codec_stream->rates;
 +      /* If the codec specifies any channels at all, it supports the stream */
 +      return codec_stream->channels_min;
  }
  
  /**
@@@ -446,42 -446,6 +446,42 @@@ static void soc_pcm_init_runtime_hw(str
        hw->rate_max = min_not_zero(hw->rate_max, rate_max);
  }
  
 +static int soc_pcm_components_open(struct snd_pcm_substream *substream,
 +                                 struct snd_soc_component **last)
 +{
 +      struct snd_soc_pcm_runtime *rtd = substream->private_data;
 +      struct snd_soc_rtdcom_list *rtdcom;
 +      struct snd_soc_component *component;
 +      int ret = 0;
 +
 +      for_each_rtdcom(rtd, rtdcom) {
 +              component = rtdcom->component;
 +              *last = component;
 +
 +              if (component->driver->module_get_upon_open &&
 +                  !try_module_get(component->dev->driver->owner)) {
 +                      dev_err(component->dev,
 +                              "ASoC: can't get module %s\n",
 +                              component->name);
 +                      return -ENODEV;
 +              }
 +
 +              if (!component->driver->ops ||
 +                  !component->driver->ops->open)
 +                      continue;
 +
 +              ret = component->driver->ops->open(substream);
 +              if (ret < 0) {
 +                      dev_err(component->dev,
 +                              "ASoC: can't open component %s: %d\n",
 +                              component->name, ret);
 +                      return ret;
 +              }
 +      }
 +      *last = NULL;
 +      return 0;
 +}
 +
  static int soc_pcm_components_close(struct snd_pcm_substream *substream,
                                    struct snd_soc_component *last)
  {
                if (component == last)
                        break;
  
 -              if (!component->driver->ops ||
 -                  !component->driver->ops->close)
 -                      continue;
 -
 -              component->driver->ops->close(substream);
 +              if (component->driver->ops &&
 +                  component->driver->ops->close)
 +                      component->driver->ops->close(substream);
  
                if (component->driver->module_get_upon_open)
                        module_put(component->dev->driver->owner);
@@@ -544,9 -510,26 +544,9 @@@ static int soc_pcm_open(struct snd_pcm_
                }
        }
  
 -      for_each_rtdcom(rtd, rtdcom) {
 -              component = rtdcom->component;
 -
 -              if (!component->driver->ops ||
 -                  !component->driver->ops->open)
 -                      continue;
 -
 -              if (component->driver->module_get_upon_open &&
 -                  !try_module_get(component->dev->driver->owner))
 -                      return -ENODEV;
 -
 -              ret = component->driver->ops->open(substream);
 -              if (ret < 0) {
 -                      dev_err(component->dev,
 -                              "ASoC: can't open component %s: %d\n",
 -                              component->name, ret);
 -                      goto component_err;
 -              }
 -      }
 -      component = NULL;
 +      ret = soc_pcm_components_open(substream, &component);
 +      if (ret < 0)
 +              goto component_err;
  
        for_each_rtd_codec_dai(rtd, i, codec_dai) {
                if (codec_dai->driver->ops->startup) {
@@@ -1005,14 -988,6 +1005,14 @@@ static int soc_pcm_hw_params(struct snd
        if (ret < 0)
                goto interface_err;
  
 +      /* store the parameters for each DAIs */
 +      cpu_dai->rate = params_rate(params);
 +      cpu_dai->channels = params_channels(params);
 +      cpu_dai->sample_bits =
 +              snd_pcm_format_physical_width(params_format(params));
 +
 +      snd_soc_dapm_update_dai(substream, params, cpu_dai);
 +
        for_each_rtdcom(rtd, rtdcom) {
                component = rtdcom->component;
  
        }
        component = NULL;
  
 -      /* store the parameters for each DAIs */
 -      cpu_dai->rate = params_rate(params);
 -      cpu_dai->channels = params_channels(params);
 -      cpu_dai->sample_bits =
 -              snd_pcm_format_physical_width(params_format(params));
 -
 -      snd_soc_dapm_update_dai(substream, params, cpu_dai);
 -
        ret = soc_pcm_params_symmetry(substream, params);
          if (ret)
                goto component_err;
@@@ -1042,16 -1025,12 +1042,16 @@@ component_err
  
        if (cpu_dai->driver->ops->hw_free)
                cpu_dai->driver->ops->hw_free(substream, cpu_dai);
 +      cpu_dai->rate = 0;
  
  interface_err:
        i = rtd->num_codecs;
  
  codec_err:
        for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) {
 +              if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
 +                      continue;
 +
                if (codec_dai->driver->ops->hw_free)
                        codec_dai->driver->ops->hw_free(substream, codec_dai);
                codec_dai->rate = 0;
@@@ -1109,9 -1088,6 +1109,9 @@@ static int soc_pcm_hw_free(struct snd_p
  
        /* now free hw params for the DAIs  */
        for_each_rtd_codec_dai(rtd, i, codec_dai) {
 +              if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
 +                      continue;
 +
                if (codec_dai->driver->ops->hw_free)
                        codec_dai->driver->ops->hw_free(substream, codec_dai);
        }
@@@ -2495,7 -2471,8 +2495,8 @@@ int dpcm_be_dai_prepare(struct snd_soc_
  
                if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
                    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
-                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
+                   (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
                        continue;
  
                dev_dbg(be->dev, "ASoC: prepare BE %s\n",