Merge tag 'asoc-fix-v5.0-rc2' into asoc-5.1
authorMark Brown <broonie@kernel.org>
Fri, 18 Jan 2019 19:14:36 +0000 (19:14 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 18 Jan 2019 19:14:36 +0000 (19:14 +0000)
ASoC: Fixes for v5.0

Quite a big batch of fixes here.  There's a couple of things going on,
the main one is that we found some issues with not deferring probe when
we should, causing us to skip some driver initialization.  The fixes for
this then in turn exposed some issues with how we were searching for
components which had previously gone unnoticed due to the original
issue.

There's also been the normal driver specific stuff and there's been what
looks like several batches of automated scanning for issues which have
generated quite a large set of smaller fixes for potential crashes and
missed error handling.

1  2 
sound/soc/codecs/tlv320aic32x4.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/glk_rt5682_max98357a.c
sound/soc/soc-core.c

index 521663d8b58587f13fd9df8e6db56294abcd8cc6,f03195d2ab2ea773b9efa52783c6b5cd7c5f368d..e1bfba62fc08f0f81dcf995238c1e74ffdd3065b
@@@ -79,32 -79,6 +79,32 @@@ struct aic32x4_priv 
        struct device *dev;
  };
  
 +static int mic_bias_event(struct snd_soc_dapm_widget *w,
 +      struct snd_kcontrol *kcontrol, int event)
 +{
 +      struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
 +
 +      switch (event) {
 +      case SND_SOC_DAPM_POST_PMU:
 +              /* Change Mic Bias Registor */
 +              snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
 +                              AIC32x4_MICBIAS_MASK,
 +                              AIC32X4_MICBIAS_LDOIN |
 +                              AIC32X4_MICBIAS_2075V);
 +              printk(KERN_DEBUG "%s: Mic Bias will be turned ON\n", __func__);
 +              break;
 +      case SND_SOC_DAPM_PRE_PMD:
 +              snd_soc_component_update_bits(component, AIC32X4_MICBIAS,
 +                              AIC32x4_MICBIAS_MASK, 0);
 +              printk(KERN_DEBUG "%s: Mic Bias will be turned OFF\n",
 +                              __func__);
 +              break;
 +      }
 +
 +      return 0;
 +}
 +
 +
  static int aic32x4_get_mfp1_gpio(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
  {
@@@ -476,9 -450,7 +476,9 @@@ static const struct snd_soc_dapm_widge
        SND_SOC_DAPM_MUX("IN3_R to Left Mixer Negative Resistor", SND_SOC_NOPM, 0, 0,
                        in3r_to_lmixer_controls),
  
 -      SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
 +      SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
 +                      SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 +
  
        SND_SOC_DAPM_OUTPUT("HPL"),
        SND_SOC_DAPM_OUTPUT("HPR"),
@@@ -850,6 -822,10 +850,10 @@@ static int aic32x4_set_bias_level(struc
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               /* Initial cold start */
+               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+                       break;
                /* Switch off BCLK_N Divider */
                snd_soc_component_update_bits(component, AIC32X4_BCLKN,
                                    AIC32X4_BCLKEN, 0);
index aefa5ce4cb592e6dc24a003b2ae8058bb39aa87a,91a2436ce9525aea53c537ba1f879456050fcc66..b0873fea23ab4e0a9c28e594b1675ba57d780296
@@@ -190,7 -190,7 +190,7 @@@ int sst_fill_stream_params(void *substr
        map = ctx->pdata->pdev_strm_map;
        map_size = ctx->pdata->strm_map_size;
  
 -      if (is_compress == true)
 +      if (is_compress)
                cstream = (struct snd_compr_stream *)substream;
        else
                pstream = (struct snd_pcm_substream *)substream;
@@@ -399,7 -399,13 +399,13 @@@ static int sst_media_hw_params(struct s
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
  {
-       snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       int ret;
+       ret =
+               snd_pcm_lib_malloc_pages(substream,
+                               params_buffer_bytes(params));
+       if (ret)
+               return ret;
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
        return 0;
  }
index 0739e3a75083f1d31b8182c42ba2f9236e5f0d5f,8f83b182c4f95d283acf52eb04cc70095778d4f4..f6597c216fa8d38d58297c05e372b6ed835653a1
@@@ -55,39 -55,6 +55,6 @@@ enum 
        GLK_DPCM_AUDIO_HDMI3_PB,
  };
  
- static int platform_clock_control(struct snd_soc_dapm_widget *w,
-                                       struct snd_kcontrol *k, int  event)
- {
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct snd_soc_card *card = dapm->card;
-       struct snd_soc_dai *codec_dai;
-       int ret = 0;
-       codec_dai = snd_soc_card_get_codec_dai(card, GLK_REALTEK_CODEC_DAI);
-       if (!codec_dai) {
-               dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
-               return -EIO;
-       }
-       if (SND_SOC_DAPM_EVENT_OFF(event)) {
-               ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
-               if (ret)
-                       dev_err(card->dev, "failed to stop sysclk: %d\n", ret);
-       } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
-                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
-               if (ret < 0) {
-                       dev_err(card->dev, "can't set codec pll: %d\n", ret);
-                       return ret;
-               }
-       }
-       if (ret)
-               dev_err(card->dev, "failed to start internal clk: %d\n", ret);
-       return ret;
- }
  static const struct snd_kcontrol_new geminilake_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@@ -102,14 -69,10 +69,10 @@@ static const struct snd_soc_dapm_widge
        SND_SOC_DAPM_SPK("HDMI1", NULL),
        SND_SOC_DAPM_SPK("HDMI2", NULL),
        SND_SOC_DAPM_SPK("HDMI3", NULL),
-       SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-                       platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-                       SND_SOC_DAPM_POST_PMD),
  };
  
  static const struct snd_soc_dapm_route geminilake_map[] = {
        /* HP jack connectors - unknown if we have jack detection */
-       { "Headphone Jack", NULL, "Platform Clock" },
        { "Headphone Jack", NULL, "HPOL" },
        { "Headphone Jack", NULL, "HPOR" },
  
        { "Spk", NULL, "Speaker" },
  
        /* other jacks */
-       { "Headset Mic", NULL, "Platform Clock" },
        { "IN1P", NULL, "Headset Mic" },
  
        /* digital mics */
@@@ -164,7 -126,7 +126,7 @@@ static int geminilake_ssp_fixup(struct 
  
        /* set SSP to 24 bit */
        snd_mask_none(fmt);
 -      snd_mask_set(fmt, SNDRV_PCM_FORMAT_S24_LE);
 +      snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
  
        return 0;
  }
@@@ -177,6 -139,13 +139,13 @@@ static int geminilake_rt5682_codec_init
        struct snd_soc_jack *jack;
        int ret;
  
+       ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
+                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
+       if (ret < 0) {
+               dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+               return ret;
+       }
        /* Configure sysclk for codec */
        ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
                                        RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
diff --combined sound/soc/soc-core.c
index 98bb05f6ed56309e2f9136bcdda24281d8b9332d,aae450ba4f08f3c02c2b23f88b50ef3e07c8e817..890d6c9c2752a024823ef715ac940a68fd731f8e
@@@ -742,7 -742,7 +742,7 @@@ static struct snd_soc_component *soc_fi
                if (of_node) {
                        if (component->dev->of_node == of_node)
                                return component;
-               } else if (strcmp(component->name, name) == 0) {
+               } else if (name && strcmp(component->name, name) == 0) {
                        return component;
                }
        }
@@@ -903,8 -903,8 +903,8 @@@ static int soc_bind_dai_link(struct snd
        for (i = 0; i < rtd->num_codecs; i++) {
                codec_dais[i] = snd_soc_find_dai(&codecs[i]);
                if (!codec_dais[i]) {
 -                      dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n",
 -                              codecs[i].dai_name);
 +                      dev_info(card->dev, "ASoC: CODEC DAI %s not registered\n",
 +                               codecs[i].dai_name);
                        goto _err_defer;
                }
                snd_soc_rtdcom_add(rtd, codec_dais[i]->component);
@@@ -1034,17 -1034,18 +1034,18 @@@ static int snd_soc_init_platform(struc
         * this function should be removed in the future
         */
        /* convert Legacy platform link */
-       if (!platform) {
+       if (!platform || dai_link->legacy_platform) {
                platform = devm_kzalloc(card->dev,
                                sizeof(struct snd_soc_dai_link_component),
                                GFP_KERNEL);
                if (!platform)
                        return -ENOMEM;
  
-               dai_link->platform      = platform;
-               platform->name          = dai_link->platform_name;
-               platform->of_node       = dai_link->platform_of_node;
-               platform->dai_name      = NULL;
+               dai_link->platform        = platform;
+               dai_link->legacy_platform = 1;
+               platform->name            = dai_link->platform_name;
+               platform->of_node         = dai_link->platform_of_node;
+               platform->dai_name        = NULL;
        }
  
        /* if there's no platform we match on the empty platform */
@@@ -1129,6 -1130,15 +1130,15 @@@ static int soc_init_dai_link(struct snd
                        link->name);
                return -EINVAL;
        }
+       /*
+        * Defer card registartion if platform dai component is not added to
+        * component list.
+        */
+       if ((link->platform->of_node || link->platform->name) &&
+           !soc_find_component(link->platform->of_node, link->platform->name))
+               return -EPROBE_DEFER;
        /*
         * CPU device may be specified by either name or OF node, but
         * can be left unspecified, and will be matched based on DAI
                        link->name);
                return -EINVAL;
        }
+       /*
+        * Defer card registartion if cpu dai component is not added to
+        * component list.
+        */
+       if ((link->cpu_of_node || link->cpu_name) &&
+           !soc_find_component(link->cpu_of_node, link->cpu_name))
+               return -EPROBE_DEFER;
        /*
         * At least one of CPU DAI name or CPU device name/node must be
         * specified
@@@ -2739,15 -2758,18 +2758,18 @@@ int snd_soc_register_card(struct snd_so
        if (!card->name || !card->dev)
                return -EINVAL;
  
+       mutex_lock(&client_mutex);
        for_each_card_prelinks(card, i, link) {
  
                ret = soc_init_dai_link(card, link);
                if (ret) {
                        dev_err(card->dev, "ASoC: failed to init link %s\n",
                                link->name);
+                       mutex_unlock(&client_mutex);
                        return ret;
                }
        }
+       mutex_unlock(&client_mutex);
  
        dev_set_drvdata(card->dev, card);